요구사항
상품의 종류는 음반, 도서, 영화가 있고 추 후 확장될 수 있음.
모든 데이터는 등록일과 수정일이 필수.
기존에서 Item을 음반, 도서, 영화의 Join 상속관계로 바꾸고
BaseEntity를 @MappedSuperclass로 만들어 공통 속성을 처리토록한다.
그럼 모든 @Entity를 BaseEntity를 상속받도록 하면되는데,
음반, 도서, 영화는 Item을 상속받으므로 Item에만 상속받도록 하면 된다.
내가 먼저 한 것
먼저 BaseEntity
@MappedSuperclass
public class BaseEntity {
private LocalDateTime createdDate;
private LocalDateTime lastModifiedDate;
}
이거를 모든 @Entity가 상속받도록 하면 된다.
@Entity
public class Member extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="MEMBER_ID")
private Long id;
private String name;
private String city;
private String street;
private String zipcode;
}
이렇게.
이제 Item과 Album, Movie, Book의 관계
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Item extends BaseEntity{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
Inheritance, 계승 하면서 전략은 JOIN으로 한다.
직접 Item을 생성할 것은 아니니 abstract로.
@Entity
public class Album extends Item{
private String artist;
}
Album. 이미 Item이 BaseEntity를 상속받았으므로, BaseEntity에 있는 요소들이 Album에도 추가가 될 것이다.
@Entity
public class Book extends Item{
private String author;
private String isbn;
}
Book.
@Entity
public class Movie extends Item{
private String director;
private String actor;
}
Movie.
나는 정석적으로 JOIN으로 했다.
이제 나가는 쿼리 몇개 보면
Hibernate:
create table Movie (
ITEM_ID bigint not null,
actor varchar(255),
director varchar(255),
primary key (ITEM_ID)
)
Hibernate:
create table Item (
price integer not null,
stockQuantity integer not null,
ITEM_ID bigint not null,
createdDate timestamp(6),
lastModifiedDate timestamp(6),
name varchar(255),
primary key (ITEM_ID)
)
Hibernate:
create table Album (
ITEM_ID bigint not null,
artist varchar(255),
etc varchar(255),
primary key (ITEM_ID)
)
Hibernate:
create table Book (
ITEM_ID bigint not null,
author varchar(255),
isbn varchar(255),
primary key (ITEM_ID)
)
이렇게 나간다.
id는 각자 가지고 있고,
공통적인 부분은 Item이 가지고 있고,
상속받은 것 들은 세부적인 걸 가졌다.
그리고 다른 테이블도 BaseEntity를 상속받았기에(@MappedSuperclass로써) createdDate와 lastModifiedDate는 모두 가지고 있다.
Album album = new Album();
album.setArtist("IU");
album.setCreatedDate(LocalDateTime.now());
album.setLastModifiedDate(LocalDateTime.now());
album.setName("좋은날");
album.setPrice(10000);
album.setStockQuantity(10);
em.persist(album);
em.flush();
em.clear();
em.find(Album.class, album.getId());
tx.commit();
이렇게 insert 해서 확인을 해 보면
이렇게 Item에도 들어가 있고,
Album에도 똑같은 id로 들어가 있다.
선생님은 일단 싱글테이블 전략으로 하신다고 한다. 하긴 이정도면 간단한 편이니 싱글테이블 전략도 괜찮다..
근데, Item이란 것이 너무 광범위 하여 확장할 요지가 너무 크다.
차례대로 보여주실 듯 싶다.
보니 categories라는 것을 만들었다.
음.. 이것도 연관관계 매핑이라고 해야 할 지..
Album, Book, Movie 싹다 조회해서 가져오면 되긴 하는데..
간단하다. 기존에서 그냥 Item의 계승 전략을 단일 테이블로 하면 된다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Item extends BaseEntity{
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
이러면 이제 나가는 쿼리는
Hibernate:
create table Item (
price integer not null,
stockQuantity integer not null,
ITEM_ID bigint not null,
createdDate timestamp(6),
lastModifiedDate timestamp(6),
DTYPE varchar(31) not null,
actor varchar(255),
artist varchar(255),
author varchar(255),
director varchar(255),
etc varchar(255),
isbn varchar(255),
name varchar(255),
primary key (ITEM_ID)
)
이다.
DTYPE이라는 게 추가 되었다. 저 이름으로 구분 될 것이다.
그리고, 이제 Album, Book, Movie 테이블은 생성하지 않는다.
Album album = new Album();
album.setArtist("IU");
album.setCreatedDate(LocalDateTime.now());
album.setLastModifiedDate(LocalDateTime.now());
album.setName("좋은날");
album.setPrice(10000);
album.setStockQuantity(10);
em.persist(album);
em.flush();
em.clear();
em.find(Album.class, album.getId());
tx.commit();
이렇게 해 봤는데,
이렇게 들어갔다.
아무래도 null이 많다. 데이터 무결성에서 문제가 있을 수 있겠다..
뭐 근데 이것도 이점이 있어서 쓴다.
아무래도 뭐 여러 장단점이 있다.
간단하게 유지할 수 있는 게 가장 좋기는 하다.
테이블 너무 많아지는 것도..