@Entity
@Table (name = "product")
public class Product {
@Embedded Id
private ProductId id;
private String name;
@Convert (converter = MoneyConverter.class)
private Money price;
private String detail;
@OneToMany ( cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true)
@JoinColumn (name = "product_id")
@Order Column (name = "list_idx")
private List<image> images = new ArrayList<>();
public void changeImages(List<Image> newImages) {
images.clear();
images.addAll(newImages);
}
}
- 상품에 이미지가 종속적임
- 이미지는 상품의 생성과 삭제의 생명주기를 동일하게 가져간다.
- 만약 이미지가 생성된 채로
- clear() 를 수행하면
- 사진이 4개면 4회의 select 가 수행되고
- 4회의 delete 로직이 수행된다.
- 상품 4000개를 삭제하는 경우
- 4000 * (8) ⇒ 32000 회의 쿼리가 수행된다.
- clear() 를 수행하면
대안
- 성능 향상을 위한
@Embeddable
활용- 엔티티 대신
@Embeddable
타입에 대한 컬렉션의 clear() 메서드 사용시- 한번의 delete 쿼리로 삭제 처리를 수행할 수 있다.
- 엔티티 대신
하지만,
- 아래 같이
- 상속 구조를 갖는 밸류타입이 사용되어 엔티티를 이용한 상속 매핑 구조로 처리된 경우
- 별도의 분기없이, discriminator 로 처리되어, 로직 처리시 타입에 대한 분기처리가 필요가 없다.
@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; @Temporal(TemporalType.TIMESTAMP) @Column (name = "upload_time") private Date uploadTime; protected Image () {} public Image (String path) { this.path = path; this.uploadTime = new Date(); } protected String getPath() { return path; } public Date getUploadTime () { return uploadTime; } public abstract String getURL(); public abstract boolean hasThumbnail(); public abstract String get ThumbnailURL() }
@Entity @DiscriminatorValue("II") public class InternalImage extends Image { } @Entity @DiscriminatorValue("EI") public class ExternalImage extends Image { }
- 하지만, Embeddable 의 경우
- 일일이 분기를 쳐야한다.
@Embeddable public class Image { @Column(name "image_type") private String imageType; @Column(name = "image_path") private String path; @Temporal(TemporalType.TIMESTAMP) @Column(name private Date uploadTime; public boolean hasThumbnail ()) { // 성능을 위해 다형을 포기하고 ifelse로 구현 if (imageType.equals("II")) { return true; } else{ return false; } } }
- 위 케이스의 경우 다형성을 포기하게 되어 유지보수성에 문제가 있을 수는 있다.
Uploaded by N2T
'도메인주도개발' 카테고리의 다른 글
밸류를 이용한 ID의 매핑 (0) | 2024.01.05 |
---|---|
밸류 매핑 애그리거트 (0) | 2024.01.05 |
애그리거트? (0) | 2024.01.02 |
애그리거트 간의 참조 (0) | 2024.01.02 |
애그리거트를 팩토리를 사용하기 (0) | 2024.01.02 |