JPA

값 타입 컬렉션(Collection Value Type)

dev-rootable 2023. 8. 18. 15:40

📌 값 타입 컬렉션(Collection Value Type)

 

값 타입 컬렉션

 

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

 

데이터베이스는 컬렉션을 같은 테이블에 저장하지 않기 때문에, 실행하면 컬렉션을 저장하기 위한 별도의 테이블이 생성된다.

 

FAVORITE_FOOD와 ADDRESS 컬렉션 테이블 추가

 

컬렉션을 위한 별도 테이블이 생성됨

 

📌 사용 방법

 

🔎 저장

 

Member에 컬렉션 셋팅

 

Member만 저장해도 컬렉션도 함께 저장됨

 

서로 다른 테이블임에도 불구하고 Member만 persist해도 함께 저장되었다.

 

그 이유는 값 타입은 Entity의 생명 주기에 의존하기 때문에 Entity를 저장하면 함께 저장되기 때문이다.

 

💡  값 타입 컬렉션은 영속성 전이 + 고아 객체 제거 기능을 필수로 가진다.

 

🔎 조회

 

값 타입 컬렉션은 기본적으로 지연 로딩 전략을 사용한다.

 

 

Member를 조회하면 Member만 단독 조회한다

 

이렇게 지연 로딩을 사용하는 이유는 @ElementCollection의 FetchType이 LAZY가 기본으로 되어 있기 때문이다.

 

@ElementCollection 속성

 

✔ 직접 조회

 

컬렉션 값 타입을 직접 조회하려면 아래와 같이 하면 된다.

 

addressHistory와 favoriteFood 직접 조회

 

조회 결과

 

🔎 수정

 

값 타입은 불변 객체여야 하므로, 최초 생성자를 통한 입력 후 값을 마음대로 변경하지 못하도록 해야 한다.

 

private로 수정자를 막거나, 인스턴스를 교체하는 방식으로 변경해야 한다.

 

새 인스턴스를 생성하여 변경

 

또 다른 방법은 컬렉션에서 특정 값을 검색하여 삭제 후 추가하는 것이다.

 

String 타입은 불변 객체

 

Address 인스턴스 삭제 후 등록

 

기본적으로 컬렉션은 equals()를 통해 객체를 찾기 때문에 equals()를 동등성 비교를 하도록 미리 오버라이딩해야 한다.

 

다음 글의 값 타입의 비교 부분 참고

 

https://dev-rootable.tistory.com/100

 

📌 제약 사항

 

  • 값 타입은 Entity와 다르게 식별자 개념이 없어 추적이 어렵다.
  • 값 타입 컬렉션에 변경 사항이 발생하면 주인 Entity와 연관된 모든 데이터를 삭제하고 값 타입 컬렉션에 있는 현재 값들을 모두 다시 저장한다.
  • 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 한다.
    • NULL 입력 x, 중복 저장 x

 

🔎 대안

 

실무에서는 상황에 따라 값 타입 컬렉션 대신 일대다 관계를 고려한다. 일대다 관계를 위한 엔티티를 만들고, 아래와 같은 wrapping 작업을 하면 Address 임베디드
값 타입이 아닌 엔티티와 관계를 맺게 된다. 또한 cascade와 orphanRemoval 속성을 통해 값 타입 컬렉션이 가졌던 기본 속성을 그대로 살릴 수 있다.

 

AddressEntity로 Address를 wrapping

 

일대다 단방향

 

이렇게 하면 엔티티와 관계를 맺기 때문에 쿼리 최적화하기 용이하고, 활용도가 높아진다.

 

AddressEntity 저장

 

ADDRESS는 PK를 가진 Entity로 승격되었다

 

식별자가 필요하고 지속해서 값을 추적, 변경해야 한다면 값 타입이 아닌 엔티티

 

Reference:

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

초급자를 위해 준비한 [웹 개발, 백엔드] 강의입니다. JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자

www.inflearn.com