[JPA] 상속 관계 매핑

olsohee·2023년 6월 22일
0

JPA

목록 보기
4/21
post-thumbnail

1. 상속 관계 매핑

관계형 데이터베이스에는 상속이라는 개념이 없다. 대신 슈퍼타입 서브타입 관계(Super Type Sub Type Relationship)이라는 모델링 기법이 객체의 상속 개념과 가장 유사하다. ORM에서 이야기하는 상속 관계 매핑은 객체의 상속 구조데이터베이스의 슈퍼타입 서브타입 관계를 매핑하는 것이다.

슈퍼타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현할 때는 다음과 같은 3가지 방법을 선택할 수 있다.

  • 조인 전략: 각각의 테이블로 변환하고, 조회할 때 조인을 사용한다.

  • 단일 테이블 전략: 테이블을 하나만 사용해서 통합한다.

  • 구현 클래스마다 테이블 전략: 서브타입마다 하나의 테이블을 만든다.


2. 조인 전략

  • 조인 전략은 엔티티 각각을 모두 테이블로 만들고, 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {}
  • 부모 클래스에 @Inheritance(strategy = InheritanceType.JOINED) 어노테이션을 사용해서 조인 전략을 적용한다.

  • 부모 클래스에 @DiscriminatorColumn(name = "DTYPE")을 통해서 구분 칼럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분할 수 있다. 기본 값이 DTYPE이므로 이름을 생략하고 @DiscriminatorColumn으로 줄여서 사용해도 된다.

@Entity
@DiscriminatorValue(name = "M")
@PrimaryKeyJoinColumn(name = "movie_id")
public class movie extends Item {}
  • 부모 테이블의 구분 칼럼에는 기본적으로 자식 테이블의 테이블 명이 저장된다. 만약 구분 컬럼을 따로 지정하고 싶으면 @DiscriminatorValue을 사용하면 된다.

  • 기본 값으로 자식 테이블은 부모 테이블의 id 칼럼명을 그대로 사용하는데, 만약 자식 테이블의 기본 키 칼럼명을 변경하고 싶으면 @PrimaryKeyJoinColumn을 사용하면 된다.

장점

  • 테이블이 정규화된다.

  • 외래 키 참조 무결성 제약조건을 활용할 수 있다.

  • 저장공간을 효율적으로 사용한다.

단점

  • 조회할 때 조인이 많이 사용되므로 성능 저하가 발생할 수 있다.

  • 조인으로 인해 조회 쿼리가 복잡해진다.

  • 데이터를 등록할 때 insert 쿼리가 두 번 실행된다. (ex, 영화 하나를 등록할 때 movie, item 두 테이블에 insert 쿼리가 나간다.)


3. 단일 테이블 전략

  • 단일 테이블 전략은 테이블을 하나만 사용하고, 구분 칼럼으로 어떤 자식 데이터가 저장되어있는지 구분하는 전략이다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {}
  • 부모 클래스에 @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 어노테이션을 사용해서 단일 테이블 전략을 적용한다.

  • 테이블 하나에 모든 자식 엔티티를 저장하므로, 구분 컬럼을 필수로 사용해야 한다.

장점

  • 조인이 필요 없으므로 일반적으로 조회 성능이 가장 빠르다.

  • 조회 쿼리가 단순하다.

단점

  • 하나의 테이블만 사용하기 때문에, 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다. 예를 들어 book 엔티티를 저장하면 item 테이블의 author, isbn만 사용하고 다른 자식 엔티티와 매핑된 artist, director, actor 컬럼은 사용하지 않으므로 null이 입력된다.

  • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 따라서 상황에 따라서는 조회 성능이 오히려 느려질 수 있으나, 자주 발생하지는 않는다.

특징

  • 구분 칼럼을 반드시 사용해야 한다. 따라서 @DiscriminatorColumn을 꼭 설정해야 한다.

  • @DiscriminatorValue를 지정하지 않으면 기본적으로 엔티티 이름을 사용한다. (ex, Movie, Album, Book)


4. 구현 클래스마다 테이블 전략

  • 구현 클래스마다 테이블 전략은 자식 엔티티마다 테이블을 만들고, 자식 테이블 각각에 필요한 컬럼이 모두 있는 전략이다.

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item {}
  • 부모 클래스에 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 어노테이션을 사용해서 구현 클래스마다 테이블 전략을 사용한다.

장점

  • 서브 타입을 구분해서 처리할 때 효과적이다.

  • not null 제약 조건을 사용할 수 있다.

단점

  • 여러 자식 테이블을 통합해서 쿼리하기 어렵다.

특징

  • 구분 칼럼을 사용하지 않는다.

  • 이 전략은 일반적으로 추천하지 않는 전략이다.

profile
공부한 것들을 기록합니다.

0개의 댓글