밸류 컬렉션을 엔티티로 매핑하기
- 개념적으로 밸류지만 구현 기술의 한계나 팀 표준 때문에 엔티티로 사용해야 할 때가 있다.
- 이때 밸류 컬렉션을 엔티티로 매핑한다.
- JPA는 @Embeddable 타입의 클래스 상속 매핑을 지원하지 않기 때문에 @Entity를 이용한 상속 매핑으로 처리해야 한다.
- 밸류 타입을 @Entity 로 매핑하므로 식별자 컬럼을 추가해야한다.
- 밸류 타입을 엔티티로 매핑했으므로 상태 변경 메서드를 구현하지 않는다.
- 한 테이블에 하위 클래스를 매핑하므로 @Inheritance strategy 속성값에 InheritanceType.SINGLE_TABLE로 설정하고
- @DiscriminatorColumn으로 구분할 컬럼명을 설정한다.
- 나누어진 엔티티에 @DiscriminatorValue로 구분할 컬럼의 값을 설정한다.
엔티티 예시
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "image_type")
@Table(name = "image")
public abstract class Image {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "image_id")
private Long id;
@Column(name = "image_path")
private String path;
...
}
@Entity
@DiscriminatorValue("II")
public class InternalImage extends Image {
...
}
@Entity
@DiscriminatorValue("EI")
public class ExternalImage extends Image {
...
}
매핑 예시
- Entity로 매핑하기 때문에 @OneToMany를 사용한다.
- changeImages() 메서드를 보면 이미지 교체를 위해 clear()을 사용하고 있다.
- Entity에 대한 @OneToMany 매핑에서 컬렉션의 clear()을 사용하면
select 쿼리로 대상 엔티티를 로딩하고 각 개별 엔티티에 대해 delete 쿼리를 실행하기 때문에
효과적이지 않을 수 있다.
- @Embeddable로 매핑된 경우 clear()를 사용하면 한번에 delete 쿼리로 삭제 처리가 가능하다.
- 하지만 나눠지는 타입에 따라 if-else를 써야하는 단점이 발생한다.
- 코드 유지보수와 성능 두 가지 측면을 고려해서 구현 방식을 선택해야 한다.