값 타입과 불변 객체 그리고 값 타입 컬렉션

박준수·2023년 3월 11일
0

[JPA]

목록 보기
14/14
post-custom-banner

값 타입과 불변객체

임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험함

회원1과 회원2의 임베디드 타입을 다음과 같이 공유해보았다.

member1.getHomeAddress().setCity("newCity"); 로 회원1의 도시를 바꿔보았다.
!!! 쿼리가 두번 나갔다 !!! 회원1의 CITY뿐만 아니라 회원2의 CITY역시 newCity로 바뀌었다.

값 타입의 실제 인스턴스인 값을 공유하는 것은 위험하기에 대신 값(인스턴스)를 복사해서 사용해야한다!!

객체 타입의 한계

  • 항상 값을 복사해서 사용하면 공유 참조로 인해 발생하는 부작용을 피할 수 있다.
  • 문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다.
  • 자바 기본 타입에 값을 대입하면 값을 복사한다.(참조 X)
  • 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.
  • 객체의 공유 참조는 피할 수 없다.

해결 방안 : 불변 객체
값 타입을 수정할 수 없게 설계하면 부작용(공유 참조)를 원천 차단!
값 타입을 불변 객체(생성 시점 이후 절대 값을 변경할 수 없는 객체)로 설계하면 됨

  • 생성자로만 값을 설정하고 수정자(Setter)를 만들지 않으면 됨
Address newAddress = new Address("newCity", address.getStreet(),address.getZipcode());
member.setHomeAddress(newAddress);

수정자(Setter)를 만들지 않으면 다음과 같이 완전히 통으로 다시 세팅해야한다.

값 타입 컬렉션

값 타입을 하나 이상 저장할 때 사용

  • 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
  • 컬렉션을 저장하기 위한 별도의 테이블이 필요함

값 탑입 컬렉션 저장

em.pesist(member) 한 번으로 다음과 같이 favorite_food, address_history 테이블이 생성되었다. 둘 다 값 타입이기에 별도의 persist()를 안해도 된다.

값 타입 조회

임베디드 타입은 즉시 로딩, 값 타입 컬렉션은 지연 로딩

값 타입 수정


값 타입 컬렉션에서는 완전히 제거 후 추가한다 new Address 같은 경우 equals를 오버라이딩하여 같은 Address를 지울 수 있도록 한다.

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(city, address.city) && 
        	   Objects.equals(street, address.street) && 
               Objects.equals(zipcode, address.zipcode);
    }
    @Override
    public int hashCode() {
        return Objects.hash(city, street, zipcode);
    }

참고: 값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.

값 타입 컬렉션의 제약 사항

  • 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.
  • 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 함: null 입력X, 중복 저장X
  • 값 타입은 엔티티와 다르게 식별자 개념이 없다.
  • 값은 변경하면 추적이 어렵다.
  • 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려

정리

엔티티 타입의 특징
• 식별자O
• 생명주기관리
• 공유

값 타입의 특징
• 식별자X
• 생명 주기를 엔티티에 의존
• 공유하지 않는 것이 안전(복사해서 사용)
• 불변 객체로 만드는 것이 안전

profile
방구석개발자
post-custom-banner

0개의 댓글