개발공부/DATABASE

[JPA] 상속관계 매핑 (조인 전략, 단일테이블 전략, 구현클래스마다 테이블 전략)

키크니개발자 2022. 6. 14. 22:52

안녕하세요!

키크니 개발자 입니다. 🦒

 

오늘은 상속관계 매핑에 대해서 알게 되어서 정리해보았습니다.

 

항상 JPA는 @ManyToOne, @OneToMany으로 연관관계만 알고있었는데

상속관계에 대해서도 매핑을 할 수 있다는 점을 처음알게되었습니다.

 

상속관계에서의 매핑은?

- 관계형 데이터베이스는 상속 관계가 없습니다.

- 슈퍼타입, 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다고 볼 수 있습니다.

- 상속관계 매핑은 객체의 상속구조DB의 슈퍼타입, 서브타입 관계를 매핑합니다.

- 크게는 조인 전략단일테이블 전략구현클래스마다 테이블 전략으로 볼 수 있습니다.

슈퍼타입, 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법

- 각각 테이블로 변환 -> 조인 전략

- 통합 테이블로 변환 -> 단일 테이블 전략

- 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략

 

아래와 같이 Item을 상속받게 된채로 아무것도 설정을 하지 않고 실행을 하게 되면,

@Entity
public abstract Item {

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}

@Entity
public class Book extends Item {

    private String author;
    private String isbn;
}

@Entity
public class Album extends Item {

    private String artist;
}

@Entity
public class Movie extends Item {

    private String director;
    private String actor;
}

아래와 같이 단일 테이블(Item)에서 모든 컬럼들이 생성되는 것을 확인할 수 있습니다. 

create table item (
       dtype varchar(31) not null,
        id bigint not null,
        name varchar(255),
        price integer not null,
        artist varchar(255),
        author varchar(255),
        isbn varchar(255),
        actor varchar(255),
        director varchar(255),
        primary key (id)
    )

이 이유는 기본적으로 Inheritance가 SINGLE_TABLE로 설정되어있기 때문입니다.

조인 전략

조인전략을 정석이라고 생각하고 테이블을 구성해야됩니다.

 

장점

- 테이블 정규화

- 외래 키 참조 무결성 제약조건으로 활용 가능

- 저장공간의 효율화

단점

- 조회시 조인을 많이 사용하여 성능 저하

- 조회 쿼리가 복잡함

- 데이터 저장시 INSERT SQL 2번 호출함

 

아래와 같이 조인 전략으로 사용하려면

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

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}

2번째 라인을 추가해줘야합니다. 설정을 JOINED로 해주게 되면 아래와 같은 결과를 얻을 수 있습니다.

Hibernate: 
    
    create table album (
       artist varchar(255),
        id bigint not null,
        primary key (id)
    )
Hibernate: 
    
    create table book (
       author varchar(255),
        isbn varchar(255),
        id bigint not null,
        primary key (id)
    )
Hibernate: 
    
    create table item (
       id bigint not null,
        name varchar(255),
        price integer not null,
        primary key (id)
    )
Hibernate: 
    
    create table movie (
       actor varchar(255),
        director varchar(255),
        id bigint not null,
        primary key (id)
    )

각 테이블의 ID는 Item 테이블의 ID라는 것을 알 수 있습니다.

단일 테이블 전략

장점

- 조인이 필요 없으므로 일반적으로 조회 성능이 빠름

- 조회 쿼리가 단순함

단점

- 자식 엔티티가 매핑한 컬럼은 모두 Null 허용 
: null 허용 한다는것이 만약 ALBUM 관련 데이터를 넣어줄 때에는 MOVIE 나 BOOK 관련 데이터는 모두 Null을 허용해줘야합니다.

- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있으며, 상황에 따라서 조회 성능이 느려질 수 있음

단일테이블을 보면 DTYPE 컬럼이 생긴것을 알 수 있습니다.

DTYPE은 어떤 테이블에 관련되서 ITEM이 사용하고 있는지에 대해 구체적으로 알 수 있게 해줍니다.

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

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}

DTYPE을 추가하고 싶을 때에는 3번째 라인을 추가하면됩니다.

DTYPE의 이름을 따로 지정하고 싶을 때에는 "" 안에 원하는 이름을 지정하게 되면 그에 따라 생성되게 됩니다.

DTYPE은 조인 전략에서는 어떻게든 관련 테이블을 찾을 수 있지만, 단일테이블 전략에서는 찾기 힘들어 꼭 들어가야 됩니다.

@DiscriminatorColumn(name = "")

그리고 DTYPE 안에 각 테이블관련된 이름을 지정하고 싶으면 

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

    private String author;
    private String isbn;
}

2번째 라인처럼 이름을 따로 지정해주면 됩니다.

 

맨 위와다르게 @Inheritance를 사용하면서 단일 테이블로 수정하고 싶을 때에는 JOINED -> SINGLE_TABLE로 변경하면 됩니다.

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

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

이 전략은 데이터베이스 설계자와 ORM 전문가 둘다 추천하지 않습니다.

 

장점

- 서브 타입을 명확하게 구분해서 처리할 때 효과적

- not null 제약 조건 사용 가능

단점

- 여러 자식 테이블을 함께 조회할 때 성능이 느림

: Item ID로 조회할 경우 어느 테이블에 들어가있는지 알 수 없으므로 union을 사용해서 ALBUM, MOVIE, BOOK을 모두 조회하게 됩니다.

- 자식 테이블을 통합해서 쿼리하기 어려움

아래와 같이 구현 클래스마다 테이블 전략으로 실행하고 싶으면 TABLE_PER_CLASS 로 변경하면 됩니다.

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

 

⭐️  참고한 곳  


자바 ORM 표준 JPA 프로그래밍 - 기본편

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

 

 

 

 

 

배워야 할 것이 더 많은 주니어 개발자입니다. 🐣
내용 전달보다는 정리를 목적으로 포스팅을 하고 있습니다.
잘못 된 내용이나 부족한 부분은 댓글로 주시면 감사드리겠습니다. 
반응형