주요 어노테이션
@Inheritance(strategy=InheritanceType.XXX)
-> JOINED: 조인 전략
-> SINGLE_TABLE: 단일 테이블 전략
-> TABLE_PER_CLASS: 구현 클래스마다 테이블 전략@DiscriminatorColumn(name=“DTYPE”)
-> 기본적으로 해당 엔티티 이름으로 저장이 됨@DiscriminatorValue(“XXX”)
예시 상황
- 앨범, 영화, 책 3개의 물품(Item)이 존재
- 공통적으로 이름(Name), 가격(Price)를 가지고 있음
- 앨범에는 작곡가(Artist), 영화는 감독(Director), 배우(Actor), 책에는 작가(Author), ISBN(isbn) 속성이 있음
각각의 테이블로 나누고, 조인을 사용하여 테이블을 구성
-> Item 테이블, Album 테이블, Movie 테이블 , Book 테이블 4개로 구분
-> Item 테이블의 ID 값이 기본키이자 나머지 3개의 테이블의 외래키로 지정
장점
-> 테이블 정규화
-> 외래 키 참조 무결성 제약 조건 활용 가능
-> 저장 공간 효율화
단점
-> 조회시 조인을 많이 사용하여 성능 저하 발생
-> 조회 쿼리가 복잡함
-> 데이터 저장시 INSERT SQL 2번 호출
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
abstract class Item(
@Id
@GeneratedValue
val id: Long? = null,
var name: String,
var price: Int
)
@Entity
class Movie(
name: String,
price: Int,
var director: String,
var actor: String
) : Item(name = name, price = price)
하나의 테이블에 각각의 속성을 다 저장하는 방법
-> 없는 것들은 Null로 저장
장점
-> 조인이 필요 없으므로 일반적으로 조회 성능이 빠름
-> 조회 쿼리가 단순
단점
-> 자식 엔티티가 매핑한 컬럼은 모두 NULL 허용 해야 함
-> 단일 테이블에 모든 것을 저장하기 때문에, 테이블이 커지고 상황에 따라 조회 성능이 떨어질 수 있음
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
abstract class Item(
@Id
@GeneratedValue
val id: Long? = null,
var name: String,
var price: Int
)
추천하지 않는 방식
각각 테이블을 별도로 구현하는 방식
장점
-> 서브 타입을 명확하게 구분해서 처리할 때 효과적
-> NOT NULL 제약 조건 사용 가능
단점
-> 여러 자식 테이블을 함께 조회할 때 성능이 느림 (UNION SQL 필요)
-> 자식 테이블을 통합해서 쿼리하기 어려움
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
abstract class Item(
@Id
@GeneratedValue
val id: Long? = null,
var name: String,
var price: Int
)
공통 매핑 정보가 필요할 때 사용
-> 등록일, 수정일, 등록자, 수정자 같은 공통 정보
상속관계 매핑, 엔티티, 테이블과 매핑이 아니다.
-> 단순히 엔티티가 공통으로 사용하는 메핑 정보를 모으는 역할
부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공
조회 불가
-> entityManager.find() 불가
직접 생성할 일이 없기에 추상 클래스로 구현
@MappedSuperclass
abstract class BaseEntity(
var createdBy: String,
var createdDate: LocalDateTime,
var lastModifiedBy: String,
var lastModifiedDate: LocalDateTime
)
@Entity
class Member(
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
val id: Long? = null,
(...)
createdBy: String,
createdDate: LocalDateTime,
lastModifiedBy: String,
lastModifiedDate: LocalDateTime
) : BaseEntity(createdBy, createdDate, lastModifiedBy, lastModifiedDate)