[JPA] 상속관계 매핑, 매핑 정보 상속에 대해 알아보자.

상속관계 매핑 - @Inheritance

관계형 DB는 상속 관계라는 개념이 없고, 슈퍼 타입, 서브 타입 관계라는 모델링 기법이 객체 상속과 유사하다.

그래서 JPA는 객체의 상속 구조와 DB의 슈퍼타입 서브타입 관계를 매핑할 수 있는 상속 관계 매핑을 지원한다.

 

JPA의 상속 관계 매핑은 총 3가지 방법이 존재한다.

  • JOIN 전략 ( JOINED )
  • 단일 테이블 전략 ( SINGLE_TABLE )
  • 구현 클래스마다 테이블 전략 ( TABLE_PER_CLASS ) - 많은 단점이 존재해 추천 X

 

상속 관계 매핑에 사용되는 주요 어노테이션은 다음과 같다.

@Inheritance(strategy=InheritanceType.??)

상속관계 매핑을 사용하는 주요 어노테이션으로 부모클래스에 해당 어노테이션을 붙여준다.

?? 에 사용하고자 하는 상속 전략을 넣어 주면 된다.

 

@DiscriminatorColumn

슈퍼타입 테이블에 있는 정보가 어느 서브타입의 정보인지를 알려주는 컬럼을 만들어주는 어노테이션이다.

기본값은  DTYPE이며  name 속성 값으로 이름을 변경할 수 있다.

 

주의할점으로, 조인 전략에서 자식 엔티티를 구분하기 위해 @DiscriminatorColumn을 꼭 선언해야한다.

그래야 자식 엔티티와 관련된 정보를 조회할 때 부모 엔티티와 연관된 정보를 참조할 수 있기 때문이다.

 

단일테이블 전략은 @DiscriminatorColumn를 선언하지않아도 자동생성된다.

단일이기 때문에 구분이 없으면 어느정보인지 구별할 수 없기 때문이다. 


JOINED 전략

각각의 엔티티를 별도의 테이블로 생성하여, 공통 속성을 가진 엔티티는 부모 테이블을 생성하고 자식 테이블에서는 자신만의 속성을 추가하는 방식으로 구현한다.

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
    ...
}
@Entity
public class Movie extends Item {
    private String director;
    private String actor;
    ...
}

 

장점 단점
테이블이 정규화 되어 있다. 조회시 조인을 많이 사용해야 해서 성능 저하가 있다.
필요없는 데이터를 저장하지 않아 저장공간을 효율적으로 사용할 수 있다. 데이터 저장시 INSERT SQL 2번씩 호출한다.

 

주의할점으로, 위에서도 설명했듯이 JOINED 전략은 @DiscriminatorColumn을 꼭 선언해야한다.

그래야 아래처럼 부모 테이블에 어떤 자식 테이블이 들어 왔는지 구분할 수 있다.


SINGLE_TABLE 전략

상속 구조의 모든 클래스 정보를 하나의 테이블에 저장하는 전략이다.

부모 클래스와 자식 클래스 간에 공통 속성뿐만 아니라 자식 클래스만의 속성도 함께 저장된다.

 

구현 방법은 JOINED과 똑같다. 전략만 SINGLE_TABLE로 변경해주면 된다.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public class Item {

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
    ...
}
@Entity
public class Movie extends Item {
    private String director;
    private String actor;
    ...
}

 

장점 단점
하나의 테이블에 저장되기 때문에 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다. 자식 엔티티가 매핑한 컬럼은 모두 null 허용한다.
테이블 구조가 단순하고 관리하기 쉽다. 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.
상황에 따라서 조회 성능이 오히려 느려질 수 있다.
INSERT 시 쿼리가 1번만 나간다. 중복 문제가 발생할 가능성이 있다.

매핑 정보 상속 - @MappedSuperclass

여러 엔티티가 공통으로 사용하는 정보를 제공하기 위해 사용한다. ( 상속 관계 매핑 X )

어노테이션은 테이블과 직접 매핑되지 않으며, @MappedSuperclass 어노테이션이 붙은 클래스를 상속받는 자식 클래스에게 매핑 정보만을 제공한다.

 

직접 생성해서 사용할 일 이 없으므로 추상 클래스 (abstract)로 생성하는 것을 권장하고 테이블이 생성되지 않으므로 조회나 검색이 불가능하다.

 

사용방법

사용방법은 간단하다.

여러 엔티티가 공통으로 갖는 정보가 있는 클래스에 @MappedSuperclass 어노테이션을 붙여주고

이 클래스를 상속 받는 엔티티는 이 클래스의 정보가 컬럼으로 생성된다.

@MappedSuperclass
public abstract class BaseEntity {
    private LocalDateTime createdDate;

    private LocalDateTime lastModifiedDate;
}
@Entity
public class Item extends BaseEntity{

    @Id
    @GeneratedValue
    private Long id;

    private String name;
    private int price;
    ...
}