관계형 데이터베이스에는 슈퍼 타입, 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
따라서 상속관계 매핑이란 객체의 상속 구조와 DB의 슈퍼 타입 서브타입 관계를 매핑하는 것이다.
이러한 슈퍼 타입 서브타입의 논리 모델을 실제 물리 모델로 구현할 때 데이터베이스에서는 다음과 같은 방법을 제공한다.
1. 각각의 테이블로 변환한다. 이를 조인 전략이라고 한다.
2. 통합 테이블로 변환한다. 이를 단일 테이블 전략이라고 한다.
3. 서브타입 테이블로 변환한다. 구현 클래스마다 테이블 전략이라고 한다.
JPA에서는 이러한 슈퍼 타입 서브타입 논리 모델을 여러 가지 방법으로 구현을 해도 전부 지원할 수 있다.
조인 전략
조인 전략은 정규화된 방식이다.
다음과 같이 매핑할 수 있다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "dtype")
@Getter @Setter
public class Item
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {
private String artist;
private String etc;
}
@Inheritance(strategy = InheritanceType.JOINED)
@Inheritance의 전략을 JOINED로 설정하면 조인 전략이 사용된다.
이 경우 자식 객체를 생성하여 저장하면 insert문이 두 개 발생한다.
조회하는 경우에는 inner join을 통해 가져온다.
@DiscriminatorColumn(name = "dtype")
@DiscriminatorColumn은 실제 부모 테이블에 생성되는데 이는 자식을 구별을 도와주는 칼럼이다.
실제 Item 조회 시 쉽게 자식의 타입이 구별이 가능하기 때문에 많은 이점이 있다.
관례상 엔티티의 이름이 들어가지만 다음 어노테이션으로 변경할 수 있다.
@DiscriminatorValue("A")
다만 조인 전략에서는 조인을 통해 자식을 가져올 수 있기 때문에 필수는 아니지만 단일 테이블 전략에서는 필수 값이다.
장점
1. 정규화
2. 왜래키 참조 무결성 제약 조건 가능
3. 필요에 따라 필요한 테이블만 접근, 저장 가능
단점
1. 조인을 사용하다 보니 성능 저하
2. 조회 쿼리 복잡함
3. 저장 시 insert sql 2번 호출
복잡하지만 만약 슈퍼 타입 서브타입을 사용한다면 나는 조인 전략을 사용할 것 같다.
정규화된 테이블로 얻을 수 있는 장점이 많고 부모 테이블을 활용하면 다른 엔티티와 연관관계에서도 사용이 그리 어렵지 않을 것 같다.
단일 테이블 전략
단순하고 성능을 위해 빈 데이터를 허용하는 경우이다. 이는 JPA의 기본 전략으로 한 테이블에 전부 칼럼을 넣는다.
SINGLE_TABLE 전략 어노테이션으로 적용할 수 있다.
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
이 경우 어노테이션이 생략되어 있어도 기본값으로 들어간다.
@DiscriminatorColumn(name = "dtype")
단일 테이블 전략은 Dtype을 구분할 수 없기 때문에 필수 값으로 들어가는 것이다.
조회도 데이터 삽입도 심플하게 하나의 쿼리로 처리 가능하다.
장점
1. 빠른 성능
2. 조회 쿼리 단순함
단점
1. 모두 null 허용
2. 만약 칼럼이 너무 많으면 임계점을 넘어 성능 저하가 될 수 있다.
구현 클래스마다 테이블 전략
아이템 테이블이 없이 구체적인 테이블을 만든다.
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Getter @Setter
public abstract class Item
만약 Item 테이블이 필요 없다면 추상 클래스로 선언해야 한다.
공통 속성이 각 테이블마다 중첩되고 각각의 테이블로 설계하는 경우 적용할 수 있다.
@DiscriminatorColumn(name = "dtype")를 사용해 구분을 할 필요가 없다.
다만 이는 조회 시 문제가 있는데, 다형성을 통해 Item 타입으로 조회하는 경우 union all로 모든 테이블을 전부 스캔한다는 점이다.
물론 특정 구현 타입으로 조회 시는 해당 테이블만 스캔한다.
장점 : 쓰지 말자.
단점 : 쓰지 말자.
대부분의 비즈니스 로직은 간단하지 않다. 이를 별도의 테이블로 구성하게 되면 동일 작업을 해당 테이블마다 처리해야 하는 경우가 발생하고 변경에도 매우 취약하다.
'데이터 접근 기술 > JPA' 카테고리의 다른 글
Hibernate 5 Bootstrapping API (0) | 2023.02.01 |
---|---|
DTO와 Entity (0) | 2022.12.11 |
값 타입 (0) | 2022.11.20 |
OSIV (0) | 2022.10.31 |
JPQL Pagination (0) | 2022.10.30 |
댓글