요구사항과 관련된 전체 엔티티는 위와 같다.
이번 포스트에서는 이들 중 상품과 관련된 엔티티에 대해서 집중적으로 다뤄보고자 한다.
[상품 엔티티]
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype")
@Getter @Setter
public abstract class Item {
@Id @GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
@ManyToMany(mappedBy = "items")
private List<Category> categories = new ArrayList<>();
}
[상품 - 도서 엔티티]
@Entity
@DiscriminatorValue("BOOK")
@Getter @Setter
public class Book extends Item {
private String author;
private String isbn;
}
[상품 - 음반 엔티티]
@Entity
@DiscriminatorValue("ALBUM")
@Getter @Setter
public class Album extends Item {
private String artist;
private String etc;
}
[상품 - 영화 엔티티]
@Entity
@DiscriminatorValue("MOVIE")
@Getter @Setter
public class Movie extends Item {
private String director;
private String actor;
}
[카테고리 엔티티]
@Entity
@Getter @Setter
public class Category {
@Id @GeneratedValue
@Column(name = "category_id")
private Long id;
private String name;
@ManyToMany
@JoinTable(name = "category_item",
joinColumns = @JoinColumn(name = "category_id"),
inverseJoinColumns = @JoinColumn(name = "item_id"))
private List<Item> items = new ArrayList<>();
// self 연관관계
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Category parent;
@OneToMany(mappedBy = "parent")
private List<Category> children = new ArrayList<>();
// 연관관계 메소드
public void addChildCategory(Category category) {
this.children.add(category);
category.setParent(this);
}
}
실무에서는 @ManyToMany를 사용하지 않는다.
@ManyToMany는 편리한 것 같지만, 중간 테이블(CATEGORY_ITEM)에 컬럼을 추가할 수 없다는 치명적인 단점을 가지고 있다. 또한 세밀하게 쿼리를 실행하기 어렵기 때문에 실무에서 사용하기에는 한계가 명확하다.
@ManyToMany 대신에 OrderItems처럼 중간 엔티티를 만들고 @ManyToOne, @OneToMany로 매핑해서 사용하는 것이 좋다.