-
JPA - @ElementCollection🌱 spring 2022. 11. 2. 17:49
값 타입 컬렉션
값 타입 컬렉션이란 컬렉션에 값 타입을 담는 것을 의미한다
- 연관관계 매핑에서 엔티티를 컬렉션으로 사용하는 것이 아닌 값 타입을 컬렉션에 쓰는 것.
값 타입❓ 엔티티 ❓
값 타입은 흔히 엔티티와 많이 비교 된다.
엔티티는 흔히 @Entity로 정의하는 객체이며 @Id라는 어노테이션으로 정의한 PK(식별자)를 통해 계속적으로 추적이 가능하다.
하지만, 값 타입은 식별자라는 개념이 존재하지 않아 추적이 어렵다.
- 값 타입은 흔히 우리가 사용하는 Integer, String 과 같은 자바 원시타입과 같은 존재이다.
- 흔히 사용하는 객체와 달리 공유에 안전하고 side effect가 발생하지 않는다.
임베디드 타입의 경우에는 구성 요소 자체가 값 타입으로 이루어져 있긴 하지만 임베디드 타입 자체가 불변 객체가 아니기 때문에 위의 장점을 포함하진 않는다.
값 타입 컬렉션
- 값 타입을 저장하는 것!! ( 값 타입을 하나 이상 저장할 때 사용 )
- 변경사항이 생기면 모두를 지웠다가 다시 만든다.
public class Member { @Id private Long id; private Set<String> favoriteFoods; private List<Address> addressHistory; }
RDB에는 내부적으로 컬렉션을 담을 수 있는 구조가 없다 ❌
- 그저 값만 넣을 수 있는 구조이다.
- 컬렉션은 1 : N의 개념이기 때문에 DB는 컬렉션을 하나의 테이블에 저장할 수 없다.
- 이런 관계를 DB 테이블에 저장하려면 별도의 테이블이 필요하다
예시
@Entity public class Member { ... @ElementCollection @CollectionTable( name = "FAVORITE_FOOD", joinColumns = @JoinColumn(name = "MEMBER_ID")) @Column(name = "FOOD_NAME") // 컬럼명 지정 (예외) private Set<String> favoriteFoods = new HashSet<>(); @ElementCollection @CollectionTable( name = "ADDRESS", joinColumns = @JoinColumn(name = "MEMBER_ID")) private List<Address> addressHistory = new ArrayList<>(); ... }
- @ElementCollection
- 값 타입 컬렉션을 구현할 수 있도록 해주는 어노테이션
- @CollectionTable
- 테이블의 이름은 어떤 것으로 할 것이고
- 조인할 때 사용할 컬럼을 지정
- @Column
- 실제 저장되는 컬럼을 설정
특징
- 값 타입이기 때문에 별도의 생명주기가 없고 엔티티의 라이프 사이클에 의존한다.
- 값 타입은 별도로 persist 또는 update를 할 필요가 없이 entity에서 값을 변경하면 자동으로 처리해줌
- 1:N 연관관계에서 Cascade = ALL로 설정하고, orphanRemoval=true로 설정한 것과 유사하다.
- 값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.
- @ElementCollection 어노테이션의 fetch 기본값은 LAZY이다.
- 컬렉션 값 타입들은 지연 로딩
- ←→ Embedded 타입의 속성들은 같이 조회 된다.
- 값 타입 컬렉션에 변경사항이 생기면 주인 엔티티와 연관된 모든 데이터를 삭제 후, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장
- 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야 한다.
- null ❌
- 중복 저장 ❌
값 타입 컬렉션 대안
실무에서는 상황에 따라 값 타입 컬렉션 대신 1:N 관계를 고려한다.
- 일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용
- 영속성 전이(Cascade) + 고아객체제거를 사용해 값 타입 컬렉션처럼 사용한다.
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "MEMBER_ID") private List<AddressEntity> addressHistory = new ArrayList<AddressEntity>();
@Entity public class AddressEntity { @Id @GeneratedValue private Long id; @Embedded Address address; ... }
@ElementCollection vs 연관관계(OneToMany, ManyToOne)
@ElementCollection
- 부모 entity에 의해 관리가 된다.
- 부모와 함께 저장되고 삭제된다.
- 컬렉션 값 변경시 → 전체 삭제, 새로 추가
연관관계
- 여러 Entity와 연관관계를 맺을 수 있다.
- 연관관계를 맺을 때 보통 ID만으로 연관을 맺는다.
참고 자료
https://gilssang97.tistory.com/74
https://insanelysimple.tistory.com/350
https://gmlwjd9405.github.io/2019/09/13/value-type-of-collection-copy.html
'🌱 spring' 카테고리의 다른 글
Spring Interceptor에서 Request 데이터 처리 (1) 2022.12.06 애플리케이션 컨텍스트와 빈팩토리 (0) 2022.11.16 JPA - Embedded Type (0) 2022.11.02 Spring Scheduler (0) 2022.10.24 Filter, Interceptor (0) 2022.10.11