[JPA] 상속 관계 매핑

1

JPA

목록 보기
8/16
post-thumbnail

객체의 상속 관계를 데이터베이스에 어떻게 매핑하는지 알아보자


상속 관계 매핑

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

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

  • 각각의 테이블로 변환(조인 전략) - 각각을 모두 테이블로 만들고 조회할 때 조인을 사용
  • 통합 테이블로 변환(단일 테이블 전략) - 테이블을 하나만 사용해서 통합
  • 서브타입 테이블로 변환(구현 클래스마다 테이블 전략) - 서브 타입마다 하나의 테이블을 만듦

조인 전략

조인 전략(Joined Strategy)은 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 PK + FK로 사용하는 전략이다. 따라서 조회할 때 조인을 자주 사용한다.

이 전략을 사용할 때는 테이블에 타입의 개념이 없기 때문에 타입을 구분하는 컬럼(DTYPE)을 추가해야한다.


ITEM

@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item{
    
    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;
    
    private String name;
    private int price;
}

MOVIE

@Getter
@Setter
@Entity
@DiscriminatorColumn("M");
public class Movie extends Item{

    private String director;
    private String actor;
}

Album

@Getter
@Setter
@Entity
@DiscriminatorColumn("A")
public class Album extends Item{

    private String artist;

}

Book

@Getter
@Setter
@Entity
@DiscriminatorColumn("B")
public class Album extends Item{

    private String author;
    private String isbn;

}

매핑 정보 분석

  • @Inheritance(strategy = InheritanceType.JOINED) : 상속 매핑은 부모 클래스에 @Inheritance를 사용해야 한다.
    속성은 strategy = InheritanceType.JOINED이며 조인 전략을 사용하겠다는 뜻이다.

  • @DiscriminatorColumn(name = "DTYPE") : 부모 클래스에 구분 컬럼을 지정한다. 속성은 name = "DTYPE"이지만 기본값도 DTYPE이므로 @DiscriminatorColumn으로 줄여 사용해도 된다.

  • @DiscriminatorValue("M") : 엔티티를 저장할 때 구분 컬럼에 입력할 값을 지정한다. 속성을 M으로 주었는데 이는 DTYPE의 값이 M이 저장되는 것이다.


장단점

장점

  • 테이블이 정규화된다.
  • 외래 키 참조 무결성 제약조건을 활용할 수 있다.
  • 저장공간을 효율적으로 사용한다.

단점

  • 조회할 떄 조인이 많이 사용되므로 성능이 저하될 수 있다.
  • 조회 쿼리가 복잡하다.
  • 데이터를 등록할 INSERT SQL을 두 번 실행한다.

단일 테이블 전략

단일 테이블 전략은 이름 그대로 테이블 하나에 자식 데이터까지 모두 저장하는 전략이다.

구분 컬럼(DTYPE)으로 어떤 자식 데이터가 저장되었는지 구분한다. 조회할 떄 조인을 사용하지 않으므로 일반적으로 가장 빠르다.

@Getter
@Setter
@Entity
@Inheritance(strategy = IngeritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item{
    
    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;
    
    private String name;
    private int price;
}

@Entity
@DiscriminatorValue("A")
public class Album extends Item{
    ...
}

@Entity
@DiscriminatorValue("M")
public class Movie extends Item{
    ...
}

@Entity
@DiscriminatorValue("B")
public class Book extends  Item{
    ...
}

장단점

장점

  • 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
  • 조회 쿼리가 단순하다

단점

  • 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
  • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 그러므로 상황에 따라서는 조회 성능이 오히려 느릴 수 있다.

마치며 ...

상속 관계 매핑에는 구현 클래스마다 테이블 전략이라는 방법도 있지만 이는 잘 활용되지 않기 때문에 넘어가도록 하겠다. 다음에는 복합 키와 식별 관계 매핑에 대해서 알아보자.

0개의 댓글