개발 일지/Spring

[JPA] @ElementCollection

미숫가루설탕많이 2023. 4. 30. 19:02

 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 옵션은 제공되지 않는다.