JPA에서 @ElementCollection 애너테이션은 관계형 데이터베이스에서 값 타입을 컬렉션으로 매핑하기 위해 사용된다. 이를 통해서 개체에 속하는 값들을 한번에 모아서 저장할 수 있다.
어 그러면 그냥 Entity에 List를 만들어서 값을 저장하면 되는 거 아닌가??
안된다. 관계형 데이터베이스는 일반적으로 컬렉션을 담을 수 있는 구조를 가지고 있지 않기 때문에 @ElementCollection 애너테이션을 통해서 값 타입 컬렉션을 매핑하는 것이다.
다음과 같은 경우에 해당 애너테이션을 사용할 수 있을 것이다.
예를 들어, 주문 엔티티는 여러 개의 주문 상품을 포함할 수 있지만 주문 상품 자체는 엔티티로서의 의미가 없는 값 타입일 것이다. 이런 경우에 엔티티를 또 사용해서 @OneToMany로 매핑하기 보다는 @ElementCollection으로 매핑해주는 것이 더 효율적이다.
@ElementCollection 애너테이션을 사용할 경우 별도의 엔티티 클래스를 만들 필요가 없고 @CollectionTable 애너테이션과 함게 사용하여 간단하게 매핑할 수 있다.
@CollectionTable은 값 타입 컬렉션을 매핑할 테이블에 대한 정보를 지정하는 역할을 한다.
다음은 그 예시이다.
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderId;
@ElementCollection
@CollectionTable(name = "order_item")
private List<OrderItem> orderItems;
}
@Embeddable
public class OrderItem {
private String name;
private int quantity;
private int price;
}
위 예시에서는 OrderItem 클래스에 선언된 name, quantity, price 필드를 각각 order_item_name, order_item_quantity, order_item_price 열로 매핑한다. 이렇게 매핑된 값 타입은 Order 엔티티의 id 값과 함께 order_item 테이블에 저장된다.
특징
- 엔티티와 달리 값 타입 컬렉션은 식별자를 갖지 않는다.
- 값 타입 컬렉션의 매핑 대상은 값 타입이며, 엔티티를 매핑할 수 없다.
- 값 타입 컬렉션을 사용할 때는 기본적으로 LAZY 로딩이 적용된다.
- 값 타입 컬렉션은 컬렉션의 크기만큼 테이블에 INSERT 쿼리가 실행되기 때문에 N+1 문제가 발생할 수 있다.
- 상위 Entity와 연관되어 관리되기 때문에 독립적으로 사용이 불가능하다. 즉, 기본적으로 cascade = ALL 이므로 cascade 옵션은 제공되지 않는다.
'개발 일지 > Spring' 카테고리의 다른 글
[Spring Security] WebMvcTest 에서 401/403 에러 해결하기 (0) | 2023.05.13 |
---|---|
[Spring] Mapstruct 클래스타입 변환 / N:M 관계 매핑 에러 (0) | 2023.05.09 |
[Spring Boot] web.xml (0) | 2023.04.12 |
[Sprgin JPA] FetchType (0) | 2023.04.09 |
[Spring WebFlux] Reactive Programming (0) | 2023.03.28 |