반응형
JPA 값 타입(Value Type)과 불변 객
JPA에서 값 타입은 복잡한 객체 세계를 단순하고 안전하게 만들기 위해 도입된 개념이다.
값 타입을 안전하게 사용하지 않으면 공유 참조로 인한 예기치 않은 부작용이 발생할 수 있다.
값 타입(임베디드)의 공유 참조 문제
임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험합니다.
예를 들어 Address 인스턴스를 두 명의 회원에게 할당하면?
Address address = new Address("서울", "강남", "12345");
Member member1 = new Member();
member1.setAddress(address);
Member member2 = new Member();
member2.setAddress(address);
member1.getAddress().setCity("부산"); // ❗ member2의 city도 "부산"으로 바뀜
값 타입 복사
공유하지 않고 안전하게 사용하려면 값(인스턴스)을 복사해서 사용해야 합니다.
Address address = new Address("서울", "강남", "12345");
Member member1 = new Member();
member1.setAddress(address);
Member member2 = new Member();
member2.setAddress(
new Address(address.getCity(), address.getStreet(), address.getZipcode())
);
객체 타입의 한계와 불변 객체
자바에서 기본 타입은 값 복사, 하지만 객체 타입은 참조 복사가 기본입니다.
객체 타입은 참조값을 직접 대입하는것을 막을 방법이 없다
불변 객체로 설계하는 방법
객체 타입을 수정할 수 없게 만들면 부작용을 원천 차단할 수 있다
- 생성자로만 필드 초기화
- setter 금지
- 모든 필드는 final로 선언 권장
- 변경 시에는 새로운 인스턴스 생성
참고: Integer, String은 자바가 제공하는 대표적인 불변객체
@Embeddable
public class Address {
private final String city;
private final String street;
private final String zipcode;
protected Address() {} // JPA용 기본 생성자
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
}
값 타입 비교
- 동일성(identity): == → 인스턴스 참조값 비교
- 동등성(equality): .equals() → 인스턴스 내부 값 비교
값 타입은 항상 동등성으로 비교해야 함
→ equals()와 hashCode() 반드시 오버라이드 필요
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Address)) return false;
Address address = (Address) o;
return Objects.equals(city, address.city)
&& Objects.equals(street, address.street)
&& Objects.equals(zipcode, address.zipcode);
}
반응형
'프로그래밍 > JPA' 카테고리의 다른 글
[JPA] JPQL 소개 (2) | 2025.07.30 |
---|---|
[JPA] 값 타입 컬렉션 (1) | 2025.07.25 |
[JPA] 값 타입 (1) | 2025.07.22 |
[JPA] 영속성 전이 CASCADE (2) | 2025.07.17 |
[JPA] 즉시 로딩과 지연 로딩 (2) | 2025.07.16 |