Super-Type Sub-Type Relationship
관계형 DB에서 객체지향에서의 상속과 유사한 개념
테이블 구현 전략
- Joined Strategy(조인 전략): 각각의 테이블로 변환하여 조회할 때 조인
- Single-Table Strategy(단일 테이블 전략): 테이블 하나에 통합
- Table-per-Concrete-Class Strategy(구현 클래스마다 테이블 전략): 서브 타입마다 테이블로 변환
Joined Strategy
- 조인 전략
- 엔티티 각각을 모두 테이블로 만듦
- Super-Type 테이블의 PK를 Sub-Type 테이블에서 PK, FK로 받아 사용
- Super-Type 테이블에서 DTYPE으로 Sub-Type 엔티티 구분
매핑 정보
- @Inheritance(strategy = InheritanceType.JOINED): 부모 클래스에 적용
- @DiscriminatorColumn(name = "DTYPE"): 부모 클래스에 구분 컬럼 지정
- @DiscriminatorValue("M"): 자식 클래스에 구분 칼럼에 입력할 값 지정
- @PrimaryKeyJoinColumn(name = "BOOK_ID"): 부모 테이블의 PK 대신 자식 테이블의 PK 컬럼명 변경
장점
- 테이블이 정규화된다
- 외래 키 참조 무결성 제약조건을 활용할 수 있다.
- 저장공간을 효율적으로 사용한다.
단점
- 조인이 많이 사용되므로 성능이 저하될 수 있다.
- 조회 쿼리가 복잡하다.
- 데이터를 등록할 때 INSERT SQL을 두 번 실행한다.
Single-Table Strategy
- 단일 테이블 전략
- 하나의 테이블에 모든 엔티티 저장
- DTYPE으로 엔티티 구분
매핑 정보
- @Inheritance(strategy = InheritanceType.SINGLE_TABLE): 부모 클래스에 적용
- @DiscriminatorColumn(name = "DTYPE"): 부모 클래스에 구분 컬럼 지정
- @DiscriminatorValue("M"): 자식 클래스에 구분 칼럼에 입력할 값 지정
장점
- 조회 쿼리가 단순하다.
- 조인이 필요 없으므로 조회 성능이 빠르다.
단점
- 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 따라서 상황에 따라서는 조회 성능이 오히려 느릴 수도 있다.
Table-per-Concrete-Class Strategy
- 구현 클래스마다 테이블 전략
- 자식 엔티티를 각각의 테이블로 만듦
- DB, ORM 측면 모두에서 추천하지 않는 전략
매핑 정보
- @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS): 부모 클래스에 적용
장점
- 서브 타입을 구분해서 처리할 때 효과적이다.
- not null 제약조건을 사용할 수 있다.
단점
- 여러 자식을 함께 조회할 때 성능이 안 좋다.
- 자식 테이블을 통합해서 쿼리하기 어렵다.
@MappedSuperclass
테이블과 매핑되지 않고 자식 엔티티에 DB 매핑정보 상속
- @AttributeOverride(name = "부모 컬럼명", column = @Column(name = "새 컬럼명")): 상속받은 부모 컬럼명 대신 새 컬럼명을 지정
- 부모 클래스는 추상 클래스로 구현하는 것을 추천