본문 바로가기
Study/JPA

[JPA] 상속관계 매핑

by DevJaewoo 2022. 8. 26.
반응형

JPA LOGO

Intro

관계형 데이터베이스에서는 기본적으로 상속 관계를 지원하지 않는다.

JPA에선 이런 문제를 해결해줄 수 있는 3가지 상속관계 매핑 방법을 지원한다.

이번 시간엔 JPA를 통해 상속 관계를 매핑하는 방법에 대해 알아보자.

 

실습하기 전 아래의 간단한 테스트용 Entity 2개를 만들어보자.

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Book extends Item {
    private String author;
    private String isbn;
}

주요 어노테이션

상속관계 매핑에는 3가지의 어노테이션이 사용된다.

  • @Inheritance(strategy=InheritanceType.XXX): 상속관계 매핑 방법을 선택한다.
    JOINED, SINGLE_TABLE, TABLE_PER_CLASS 3가지 중에서 하나를 선택할 수 있다.
  • @Discrimintaorcolumn(name="DTYPE"): 부모 클래스에서 자식 클래스를 구분하는 컬럼의 이름을 설정한다.
  • @DiscriminatorBalue("XXX"): 자식 클래스를 식별하기 위해 부모의 DTYPE 컬럼에 저장될 값을 설정한다.
    기본 값은 클래스 이름이다.

JOINED 전략

joined 전략

특징

  • 가장 추천하는 방법이다.
  • 부모 및 자식 클래스가 정의된 그대로 만들어진다.
  • 부모 클래스엔 자식 클래스 구분을 위한 DTYPE, 자식 클래스엔 JOIN을 위한 ITEM_ID 컬럼이 생성된다.

장점

  • 테이블이 정규화 되어있다.
  • 필요없는 데이터를 저장하지 않아 저장공간을 효율적으로 사용할 수 있다.

단점

  • 테이블이 분리되어있어 조회 시 JOIN을 많이 사용해야 하기 때문에 복잡하고 성능이 저하된다.
  • 테이블이 분리되어있어 INSERT 쿼리를 2번씩 호출해야 한다.
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}
@DiscriminatorValue("BOOK")
public class Book extends Item {
    private String author;
    private String isbn;
}

SINGLE_TABLE 전략

single table 전략

특징

  • 자식 클래스의 모든 속성들을 다 부모 클래스에 때려넣은 테이블을 생성한다.
  • 서비스 규모가 크지 않아 단순하게 해도 상관 없을 때 사용하기 좋다.

장점

  • JOIN이 필요없어 보통 조회 성능이 잘 나온다.
  • INSERT 시 쿼리가 1번만 나간다.

단점

  • 자식 클래스의 속성들은 모두 NULL을 허용해야 한다.
  • 자식 클래스의 속성이 많으면 많아질수록 테이블의 크기가 커진다.
    이런 경우 저장공간이 낭비되고, 조회 성능이 오히려 느려질 수 있다.
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}
@DiscriminatorValue("BOOK")
public class Book extends Item {
    private String author;
    private String isbn;
}

CLASS_PER_TABLE 전략

class per table 전략

특징

  • SINGLE_TABLE과 반대로 모든 자식 클래스에 부모 클래스의 속성을 때려넣는다.
  • 단점이 크기 때문에 추천하지 않는다.

장점

  • 서브 타입을 명확하게 구분해서 처리할 수 있다.
  • 컬럼에 NOT NULL 제약조건을 설정할 수 있다.

단점

  • 여러 자식 테이블을 함께 조회할 때 UNION을 사용해야 해서 성능이 느리다.
  • 자식 테이블을 통합해서 쿼리하기 힘들다.
  • 자식 클래스가 추가되면, 조회 코드를 변경해야 한다.
  • 쓰지 말자.
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn(name = "DTYPE")
public class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}
@DiscriminatorValue("BOOK")
public class Book extends Item {
    private String author;
    private String isbn;
}

출처

반응형

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

[JPA] 공통 속성 매핑  (0) 2022.08.26
[JPA] 연관관계 매핑  (0) 2022.08.25
[JPA] Entity 필드, 컬럼 매핑  (0) 2022.03.05
[JPA] 영속성 컨텍스트  (0) 2022.03.05
[JPA] DB에 데이터 넣어보기  (0) 2022.02.26