패턴 1 — Surrogate Key 방식 (가장 일반적)equals / hashCode 아예 구현하지 않음객체 동일성 = JVM 참조 동일성HashSet에 넣어도 안전id가 바뀌어도 hashCode 불변Hibernate 프록시도 안전@Entityclass Member( var name: String) { @Id @GeneratedValue var id: Long? = null}영속성 컨텍스트(1차 캐시)JPA는 이미 객체 동일성 컨텍스트를 갖고 있다같은 ID → 같은 객체 인스턴스 하나만 사용val m1 = em.find(Member::class.java, 1L)val m2 = em.find(Member::class.java, 1L)m1 === m2 // true////////..
@Entitydata class Member( @Id @GeneratedValue val id: Long = 0, var name: String)equals()와 hashCode() 문제: data class는 생성자에 있는 모든 필드를 사용하여 equals와 hashCode를 자동으로 만듦id = null (or 0) 인 상태로 엔티티 생성HashSet 또는 HashMap key로 사용persist() → DB가 id 생성Hibernate가 id를 새 값으로 변경hashCode() 변경 → 컬렉션에서 못 찾음equals / hashCode는 변하지 않는 식별자를 사용해야 한다순환 참조 및 지연 로딩 실패: 만약 생성자에 연관 관계(@OneToMany 등)가 포함되면, hashCod..
Body에 선언 - 안전한 Kotlin Entity 패턴 id는 클래스 바디에서 var로 선언id가 null이면 "아직 DB에 저장되지 않은 비영속(Transient) 상태자동 생성이 아니면 서비스/팩토리에서 member.id = "값" 형태로 세팅JPA는 프록시 객체 생성을 위해 기본 생성자가 필요자동으로 기본 생성자를 만들어주는 라이브러리 "plugin.noarg", "org.jetbrains.kotlin.plugin.jpa"Body에 선언하면 직접 equals와 hashCode를 구현하기 용이JPA Entity의 동등성은 오직 PK(Primary Key)로만 판단해야 안전영속화 전(Transient) 객체끼리 비교할 때도 동등으로 보고 싶은 경우는 PK 비교 안됨@Entityclass Member(..
nested class기본값: 아무 키워드 없이 클래스 안에 선언외부 클래스의 프로퍼티나 메서드에 접근할 수 없음Java로 치면 static class 와 동일class Outer { private val message = "Hello" class Nested { fun print() { // println(message) // ❌ 외부 클래스 접근 불가 println("I'm a nested class") } }}// 사용val nested = Outer.Nested()nested.print()inner classinner 키워드를 사용해야 함외부 클래스의 프로퍼티나 메서드에 접근 가능Java의 non-static inne..
What?jdk 이미지를 openjdk:11-jdk-slim 변경한 후에 엑셀 다운로드 기능이 불가java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManagerWhy?Apache POI는 sun.awt.X11FontManager을 로드해서 사용하는데openjdk:11-jdk-slim 이미지는 X11 관련 폰트 및 AWT 그래픽 라이브러리 의존성이 빠져 있어서 클래스 로딩이 실패How?일반적인 패키지가 포함된 openjdk:11-jdk 이미지로 변경
Jackson의 @JsonAnySetter는 JSON 역직렬화(deserialization) 과정에서 Java 객체에 미리 정의되지 않은 (알 수 없는) 프로퍼티들을 처리하기 위해 사용되는 어노테이션주로 동적인 JSON 데이터를 다룰 때 유용하게 활용@JsonAnySetter로 알 수 없는 데이터를 받아 Map에 저장하고, @JsonAnyGetter를 사용해 직렬화 시 Map의 데이터를 다시 JSON 필드로 풀어주는 예시 { "name": "홍길동", "itemList": [ { "id": 1, "name": "itemA", "productNo": "A1"}, { "id": 2, "name": "itemB", "imageUrl": "imagB" } ]}import com.fasterxml..
readValue()Jackson에서 JSON을 DTO 클래스(POJO)에 매핑할 때 사용String json = "{ \"id\": 1, \"name\": \"Alice\", \"age\": 28 }";ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(json, User.class);convertValue()JsonNode를 POJO 또는 Map/Collection으로 변환하는 메서드JsonNode node = mapper.readTree(json);User user = mapper.convertValue(node, User.class);Jackson 내부적으로는:JsonNode를 중간에 직렬화(serialization) → J..
Jackson의 3가지 JSON 처리 모델모델특징장점단점Streaming API빠른 처리, 메모리 효율가장 빠름, 대용량 데이터에 적합사용법이 복잡하고 직관적이지 않음Tree Model유연한 구조 탐색 가능구조가 복잡하거나 동적일 때 유용전체 JSON을 메모리에 올려야 함Data Binding자바 객체 ↔ JSON 자동 매핑가장 사용하기 쉬움속도는 스트리밍보다 느림Streaming API (스트림 기반 처리)Streaming API는 Jackson에서 가장 저수준이며, 빠르고 메모리 효율적입니다. JSON을 한 줄씩 읽고 쓰는 방식 (JsonParser, JsonGenerator)으로 동작스트리밍 방식(Forward-only 방식)을 사용하면 메모리 사용량이 적습니다. 대용량 JSON 처리에 적합pull..
무한대 크기 지원: long 범위(±9경)를 넘는 정수도 표현 가능이론적으로 메모리가 허용하는 한 무한대에 가까운 숫자까지 표현불변 객체(Immutable): 기존 값을 바꾸지 않고 항상 새로운 객체를 반환정수 연산 지원: 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지, 거듭제곱, GCD 등 다양한 연산 지원java.math 패키지에 포함import java.math.BigInteger;public class Main { public static void main(String[] args) { BigInteger big1 = new BigInteger("9223372036854775808"); // long 범위 넘어선 수 BigInteger big2 = new BigInteger(..
BigDecimal은 Java에서 정밀한 소수 계산이 필요할 때 사용하는 클래스float나 double 타입은 부동소수점 오차가 있어서 정확한 소수 계산이 필요할 때는 적합하지 않다.import java.math.BigDecimal;public class Main { public static void main(String[] args) { BigDecimal num1 = new BigDecimal("10.25"); BigDecimal num2 = new BigDecimal("3.1"); // 덧셈 BigDecimal sum = num1.add(num2); // 나눗셈 (소수점 자릿수 지정 필요) BigDecimal resul..