본문 바로가기
JPA/JPA

[JPA] 상속 관계 매핑

by 걸어가는 신사 2022. 1. 3.

1. 상속 관계 매핑

객체의 상속과 DB의 슈퍼타입 서브타입 관계를 매핑하는 것
  • 관계형 데이터베이스에는 객체지향 언어에서 다루는 상속이라는 개념이 없다.
  • 대신 슈퍼타입 서브타입 관계(Super-Type Sub-Type Relationship)이라는 모델링 기법이 객체의 상속 개념과 가장 유사하다.

슈퍼타입 서브타입 논리 모델, 객체 상속 모델

  • 슈퍼타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현할 때는 3가지 방법을 선택할 수 있다.
    • 각각 테이블로 변환 -> 조인 전략
    • 통합 테이블로 변환 -> 단일 테이블 전략
    • 서브타입 테이블로 변화 -> 구현 클래스마다 테이블 전략

 

2. 조인 전략

JOINED TABLE

  • 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다.
  • 조회할 때 조인을 사용해야 한다.
  • 객체는 타입으로 구분할 수 있지만 테이블은 타입의 개념이 없다.
  • 타입을 구분하는 컬럼을 추가해야 한다. (DTYPE)
@Entity
@Getter @Setter
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {
    private String artist;
}

@Entity
@DiscriminatorValue("B")
@Getter @Setter
public class Book extends Item{
    private String author;
    private String isbn;
}

@Entity
@DiscriminatorValue("M")
@Getter @Setter
public class Movie extends Item{
    private String director;
    private String actor;
}

(1) @Inheritance(strategy = InheritanceType.JOINED)

  • 상속 매핑은 부모 클래스에 @Inheritance를 사용해야 한다.
  • 그리고 매핑 전략을 지정해야 한다. 조인 전략을 사용하기 위해 InheritanceType.JOINED를 사용했다.

(2) @DiscriminatorColumn(name = "DTYPE")

  • 부모 클래스에 구분 컬럼을 지정한다.
  • 이 컬럼으로 저장된 자식 테이블을 구분할 수 있다.
  • 기본 값이 DTYPE이다.

(3) @DiscriminatorValue("M")

  • 엔티티를 저장할 때 구분 컬럼에 입력할 값을 지정한다.
  • 만약 영화 엔티티를 저장하면 구분 컬럼인 DTYPE에 값 M이 저장된다.

(4) 장점과 단점

  • 장점
    • 테이블이 정규화된다.
    • 외래 키 참조 무결성 제약조건을 활용할 수 있다.
    • 저장공간을 효율적으로 사용한다
  • 단점
    • 조회할 때 조인이 많이 사용되므로 성능이 저하될 수 있다.
    • 조회 쿼리가 복잡하다.
    • 테이터를 등록할 INSERT SQL을 두 번 실행한다.

 

3. 단일 테이블 전략

SINGLE TABLE

  • 테이블을 하나만 사용한다.
  • 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
    • Book 엔티티를 저장하면 ITEM 테이블의 AUTHOR, ISBN 컬럼만 사용하고 다른 엔티티와 매핑된 컬럼은 사용하지 않으므로 null이 입력된다.
@Entity
@Getter @Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {
    private String artist;
}

@Entity
@DiscriminatorValue("B")
@Getter @Setter
public class Book extends Item{
    private String author;
    private String isbn;
}

@Entity
@DiscriminatorValue("M")
@Getter @Setter
public class Movie extends Item{
    private String director;
    private String actor;
}
  • InheritanceType.SINGLE_TABLE로 지정하면 단일 테이블 전략을 사용한다.
  • 테이블 하나에 모든 것을 통합하므로 구분 컬럼을 필수로 사용해야 한다.
  • 장점
    • 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
    • 조회 쿼리가 단순하다.
  • 단점
    • 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
    • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서는 조회 성능이 오히려 느려질 수 있다.
  • 특징
    • 구분 컬럼을 꼭 사용해야 한다. @DiscriminatorColumn을 설정해야 한다.
    • @DiscriminatorValue를 지정하지 않으면 기본으로 엔티티 이름을 사용한다.
      • ex) Movie, Album, Book

 

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

CONCRETE TABLE

  • 장점
    • 서브 타입을 명확하게 구분해서 처리할 때 효과적이다
    • not null 제약조건 사용할 수 있다.
  • 단점
    • 여러 자식 테이블을 함께 조회할 때 성능이 느리다(UNION SQL 필요)
    • 자식 테이블을 통합해서 쿼리하기 어렵다.
  • 이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천하지 않는 전략이다.
  • 조인이나 단일 테이블 전략을 사용하자.
반응형

'JPA > JPA' 카테고리의 다른 글

[JPA] 프록시 (Proxy)  (0) 2022.01.03
[JPA] @MappedSuperclass  (0) 2022.01.03
[JPA] 연관관계 매핑 - 2  (0) 2022.01.02
[JPA] 연관관계 매핑 - 1  (0) 2022.01.01
[JPA] 엔티티 매핑 (Entity Mapping)  (0) 2021.12.31

댓글