상속관계 매핑
@MappedSuperclass
객체에는 상속관계가 있으나, 관계형 데이터베이스는 상속관계가 없다.
슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
슈퍼타입 서브타입 논리모델 -> 물리모델로 구현하는 방법
@Inheritance(strategy=InheritanceType.XXX)
를 활용
• JOINED: 조인 전략
• SINGLE_TABLE: 단일 테이블 전략
• TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
#### 1 ) (추천)(정석)(복잡)각각 테이블로 변환 = 조인전략을 사용<br/>
: <br/>
[방법]상속관계에서 가장 부모인 객체에 `@Inheritance(strategy=InheritanceType.JOINED)` 작성<br/>
:<br/>
[쿼리문] 값을 넣으면 부모 테이블의 ID값이 자식 테이블의 ID값에 FK, PK로 들어가게 된다. 즉 INSERT 쿼리문 2회<br/>
:<br/>
[조회쿼리문]`em.persist(movie); em.flush(); em.clear();` 하고 나서 `em.find(Movie.class, movie);` 를 하면 inner join 쿼리가 날아간다. 즉 join 쿼리문 1회가 필요하게 된다.
<br/>
:<br/>
[장점] 저장공간 효율화/외래키 참조 무결성 제약조건 활용을 통해 한번에 조회가능
[단점] 복잡해질수록 성능 저하/조회쿼리 복잡해짐/데이터 저장시 INSERT SQL 2번 호출 <br/>
```java
Hibernate:
/* insert jpabook.Movie
*/ insert
into
Item
(name, price, ITEM_ID)
values
(?, ?, ?)
Hibernate:
/* insert jpabook.Movie
*/ insert
into
Movie
(actor, director, ITEM_ID)
values
(?, ?, ?)
Hibernate:
select
movie0_.ITEM_ID as ITEM_ID1_5_0_,
movie0_1_.name as name2_5_0_,
movie0_1_.price as price3_5_0_,
movie0_.actor as actor1_9_0_,
movie0_.director as director2_9_0_
from
Movie movie0_
inner join
Item movie0_1_
on movie0_.ITEM_ID=movie0_1_.ITEM_ID
where
movie0_.ITEM_ID=?
```
<br/>
:<br/>
[DTYPE]<br/>
• DTYPE = 부모 테이블에 값이 입력되었는데, 어떤 자식으로부터 값이 입력된 것인지 알고 싶을 때 사용<br/>
• [사용방법] 부모 객체에 `@DiscriminatorColumn` 작성, `@DiscriminatorColumn(name=“DTYPE”)` 이름 지정 가능<br/>
• 추가적으로, 부모테이블에 저장되는 자식테이블에 대한 DTYPE값도 변경할 수 있다.
• [방법] 자식 객체에 `@DiscriminatorValue(“XXX”)` 이름 지정 가능<br/>
#### 2 )(추천)(단순) 통합 테이블로 변환 = 단일 테이블 전략을 사용(DEFAULT)<br/>
:<br/>
[쿼리문] INSERT 쿼리문이 1회만 만들어지므로 가장 성능이 좋고 find로 찾을 때에도 join의 필요가 없다.
:<br/>
[방법] 상속관계에서 가장 부모인 객체에 `@Inheritance(strategy=InheritanceType.SINGLE_TALBE)` 작성<br/>
:<br/>
[DTYPE]<br/>
• [사용방법] 부모 객체에 `@DiscriminatorColumn`를 생략해도 자동으로 DTYPE칼럼이 생긴다. <br/>
:<br/>
[장점] 조인이 필요 없으므로 일반적으로 조회 성능이 빠름/조회쿼리 단순
[단점] 자식 엔티티가 매핑한 컬럼은 모두 null 허용/단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.<br/>
#### 3 ) (비추천)서브타입 테이블로 변환 = 구현 클래스마다 테이블 전략을 사용 **(사용해서는 안되는 전략)** <br/>
: <br/>
[방법]<br/>
• 상속관계에서 가장 부모인 객체에 `@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)` 작성<br/>
• 부모 클래스를 abstract class 추상 클래스로 작성(객체, 테이블 생성 X)
공통의 매핑정보가 필요할 때 사용
테이블과 매핑되지 않는다.
상속관계 매핑 X
직접 생성할 일이 없으므로, abstract class 추상 클래스로 생성(객체, 테이블 생성 X)
조회, 검색 불가(em.find(BaseEntity) 불가)
테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할
주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용
@Entity : 상속관계 매핑할 때 사용
@MappedSuperclass : 공통으로 사용하는 매핑정보 모을 때 사용
package jpabook;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@MappedSuperclass
public class BaseEntity {
private String createdBy;
private LocalDateTime createdDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public LocalDateTime getCreatedDate() {
return createdDate;
}
public void setCreatedDate(LocalDateTime createdDate) {
this.createdDate = createdDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
public LocalDateTime getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(LocalDateTime lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
}
@Entity
public class Member extends BaseEntity{
...
}
다음과 같이 사용한다.