관계형 DB는 상속 관계 X
슈퍼타입 - 서브타입 관계 : 객체 상속과 유사
상속관계 매핑 : 객체의 상속 구조
/ DB의 슈퍼타입 - 서브타입
관계를 매핑
주요 @
@Inheritance(stategy = InheritanceType.XXX)
@DiscriminatorColumn
name
: "DTYPE" (defalut)@DiscriminatorValue
DTYPE
의 값을 변경할 수 있다.🧨슈퍼타입 - 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법 3가지
⭕1) 조인 전략 (각각 테이블로 변환) - 정석
상품
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {
@Id
@GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
}
앨범, 영화, 책
@Entity
public class Album extends Item{
private String artist;
}
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
메인
try {
Movie movie = new Movie();
movie.setDirector("aaaa");
movie.setActor("bbbb");
movie.setName("바람과 함께 사라지다");
movie.setPrice(10000);
em.persist(movie);
tx.commit();
}
DB 결과
장점
단점 (SINGLE_TABLE
전략과 비교)
⭕2) 단일 테이블 전략 (통합 테이블 변환) - 단순할 때 사용
DTYPE을 사용해 구분 ⇒ If, @DiscriminatorColumn
없다면? 저절로 생긴다. 꼭 필요하기 때문이다.
Item.class
의 상속 전략을 SINGLE_TABLE
로 변경, 메인 그대로 실행
DB 결과
장점
단점
⭕3) 구현 클래스마다 테이블 전략 (서브타입 테이블로 변환) - 쓰지 마세용!
Item.class
를 추상화(abstract
)하고 상속 전략을 TABLE_PER_CLASS
로 변경 + DTYPE 필요 없음
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
}
쓰지 말아야 하기 때문에, 장/단점 X
공통 매핑 정보가 필요할 때 사용(id, name)
귀찮음을 타개하기 위해 추상 클래스를 통해 속성만 공동적으로 묶는다.
예를 들어, 등록/수정에 필요한 정보가 있다.
BaseEntity
@MappedSuperclass
public abstract class BaseEntity {
private String createdBy;
private LocalDateTime createdDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
}
Member
@Entity
public class Member extends BaseEntity{
...
}
extends BaseEntity
사용특징
em.find(BaseEntity.class, PK)
불가)요구사항
도메인 모델
테이블 설계
Item
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item extends BaseEntity {
@Id
@GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
@OneToMany(mappedBy = "item")
private List<CategoryItem> categoryItems = new ArrayList<>();
}
음반, 책, 영화
@Entity
public class Album extends Item {
private String artist;
private String etc;
}
@Entity
public class Book extends Item {
private String author;
private String isbn;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
BaseEntity (등록일, 수정일)
@MappedSuperclass
public abstract class BaseEntity {
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
}
메인
try{
Book book = new Book();
book.setName("JPA");
book.setAuthor("jinmin");
em.persist(book);
tx.commit();
}
DB 결과