상속관계 매핑: 객체의 상속 관계와 DB의 슈퍼타입, 서브타입 관계 매핑
- 객체는 상속관계 존재
- RDB는 상속관계 X
- 슈퍼타입, 서브타입 관계라는 유사한 논리 모델링 기법 존재
- 이 논리 모델을 물리 모델로 구현하는 방법
- 1. 조인 전략
- 2. 단일 테이블 전략
- 3. 구현 클래스마다 테이블 전략
- 객체 입장에서는 아무 변화가 없고, DB설계를 어떻게 할 것이냐 결정하는 것
- JPA는 세가지 방법 모두 지원 (기본 설정: 단일 테이블 전략)
// Item class
@Entity
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
// Album class
@Entity
public class Album extends Item {
private String artist;
}
// Movie class
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
// Book class
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
1. 조인 전략: 각각 테이블로 변환
- 저장 시 각각의 필드에 매핑된 컬럼이 속한 테이블에 맞게 저장 (INSERT 두번)
- 조회 시 해당하는 두 테이블을 조인하여 조회
- DTYPE으로 ALBUM인지 MOVIE인지 BOOK인지 구별 (사용 권장)
- DTYPE 사용하면 ITEM 테이블만 확인해도 어떤 상품 종류인지 확인 가능
- 조인 전략에서는 DTYPE 활성화 하지 않아도 작동하지만 나머지 전략에는 필수
// Item class
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 조인 전략
@DiscriminatorColumn // DTYPE 사용
// @DiscriminatorColumn(name="DIS_TYPE")
public class Item {
// Album class
@Entity
@DiscriminatorValue("A") // DTYPE 컬럼에 들어갈 이름 (기본값: 엔티티 이름)
public class Album extends Item {
// id 생략하면 부모의 id(ITEM_ID)가 id가 됨
//@Id @GeneratedValue
//private Long id;
SELECT * FROM ITEM;
DTYPE | ID | NAME | PRICE |
A | 1 | n | 100 |
2. 단일 테이블 전략: 통합 테이블로 변환
- 한 테이블에 합치고 DTYPE으로 구분
- 테이블이 커지면 성능 저하 우려 (흔하지 않은 경우임)
- 저장 시 INSERT 한번에, 조회시 조인 없이 SELECT 한번 -> 좋은 성능
- 자식 엔티티가 매핑한 컬럼은 모두 null 허용
- 위 경우 NAME, PRICE 제외하고 모두 null 허용해주어야 하므로 데이터 무결성의 측면에서 단점이 될 수 있다
- @DiscriminatorColumn 없어도 자동으로 DTYPE 활성화
// Item class
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // 생략 가능
@DiscriminatorColumn // 생략 가능
public class Item {
3. 구현 클래스마다 테이블 전략: 서브타입 테이블로 변환 (사용하지 말 것!)
- ITEM 테이블 생성되지 않고 ITEM의 컬럼들을 서브타입 테이블에 중복되게 저장 (여기선 NAME, PRICE 컬럼)
- 저장 시 INSERT 한번에, 조회시 조인 없이 SELECT 한번
- 대신 ITEM_ID로 조회한다면 세 서브타입 테이블에 SELECT 다 날려서 찾아야 함 (비효율적)
- 연결되어 있지 않기 때문에 통합해서 쿼리하기 어렵고, 시스템에 변경이 생겼을 때 많은 부분을 고쳐야 함
// Item class
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
//@DiscriminatorColumn // 필요없음
public abstract class Item { // 추상 클래스로 해야 맞음
기본적으로 조인 전략으로 가져가되,
상황이 단순하고, 확장 가능성도 적다면 단일 테이블 전략 사용
@MappedBySuperclass
- 공통 매핑 정보가 필요할 때 사용 (예: id, name)
// BaseEntity class
@MappedSuperclass
public abstract class BaseEntity { // 추상 클래스 권장
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
}
// Member class
@Entity
public class Member extends BaseEntity {
// Team class
@Entity
public class Team extends BaseEntity {
- 상속 관계 매핑 x
- BaseEntity는 테이블로 생성되지 않음, 조회 및 검색 불가
- 참고: @Entity가 붙은 클래스는 @Entity나 @MappedSuperclass가 붙은 클래스만 상속받을 수 있음
출처: 김영한님 JPA 프로그래밍 입문
'course > inflearn' 카테고리의 다른 글
[JPA 프로그래밍 기본편] 값 타입 (0) | 2022.09.18 |
---|---|
[JPA 프로그래밍 기본편] 프록시와 연관관계 관리 (0) | 2022.09.09 |
[JPA 프로그래밍 기본편] 다양한 연관관계 매핑 (0) | 2022.09.03 |
[JPA 프로그래밍 기본편] 연관관계 매핑 기초 (0) | 2022.09.01 |
[JPA 프로그래밍 기본편] 엔티티 매핑 (0) | 2022.08.31 |