[JPA기본] 7. 고급 매핑

kiwonkim·2021년 12월 10일
0
post-custom-banner

[ 이전 포스팅 ]

이전 포스팅을 통해 1:1, 1:N, N:M 관계에서 @OneToMany 와 @MappedBy 등을 활용해 연관관계 매핑을 수행하였다. 연관관계 주인이란 객체의 값을 변경시키면 테이블의 FK 값이 바뀌는 클래스를 말하며, 보통 FK 를 갖는 쪽으로 설정한다.

상속관계 매핑과 공통 속성을 모으는 방식에 대해 알아보자.


[ 상속관계 매핑 ]

객체의 상속관계

Java 에서 객체는 상속관계를 가질 수 있다. 그런데 RDB 에는 상속관계가 없는 대신 슈퍼타입과 서브타입이라는 것이 있다. 그러면 @Entity 클래스간에 상속관계가 있다면 이는 어떻게 매핑될까? JPA 에는 상속관계의 매핑에 세가지 전략을 사용할 수 있다.


[ 조인 전략 ]

조인 전략이란

조인 전략이란 상속관계 매핑시 부모 클래스의 PK 를 자식 클래스에서 FK 를 갖도록 구현되는 전략을 말한다. 부모와 자식클래스가 각각의 테이블로 구현된다.

적용법

부모 클래스에 @Inheritance(strategy = InheritanceType.JOINED) 를 추가한다.

장단점

중복이 제거되어 테이블이 정규화되나, 조회시 부모와 Join 을 하여 결과를 생성한다. 또한 데이터 저장시 부모와 자식 테이블에 나눠서 저장되어 INSERT 가 두번 호출된다.

Discriminator

어떤 자식테이블 때문에 삽입된 것인지 표시하는 식별자 속성.

@DiscriminatorColumn(name="DTYPE")
-> 부모테이블에 어떤 자식테이블 때문에 삽입된 것인지 속성을 추가한다.

@DiscriminatorValue("xxx")
-> 자식 테이블에 자신의 식별자 이름을 정의한다.

삽입결과

부모 테이블인 ITEM 에 공통속성이 저장되며.
자식 테이블인 MOVIE 에 ID 를 FK 로 갖는 것을 볼 수 있다.


[ 단일 테이블 전략 ]

단일 테이블 전략이란

자식 테이블을 생성하지 않고, 부모 엔티티와 자식 엔티티를 부모 테이블에 때려박는 전략이다.

적용법

디폴트 전략이라 상속관계를 매핑하게 되면 자동으로 단일 테이블 전략을 사용한다. 또는 부모 테이블에 strategy 를 SINGLE_TABLE 로 설정한다.

장단점

조인이 필요없어 일반적으로 조회 성능이 빠르나, 다른 자식 테이블 컬럼은 null 값을 갖게되므로 nullable 로 설정해야한다.

삽입결과

부모 테이블인 ITEM 에 자식 테이블의 모든 속성이 다 들어간다.
자식 테이블은 생성되지 않는다.
또한 @DiscriminatorColumn 은 어노테이션을 추가하지 않아도 자동으로 생성된다.


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

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

부모 엔티티를 테이블로 생성하지 않고, 각각의 자식테이블들을 생성하는 전략이다.

적용법

strategy 로 TABLE_PER_CLASS 를 설정한다.

장단점

단일 테이블과 달리 not null 을 사용할 수 있으나, 묶어서 관리되지 않기에 부모 컬럼으로 조회시 매우 속도가 느리다. 예를 들어 Item 의 PK 인 Id 로 검색을 수행하면, 세개의 자식 테이블을 모두 뒤져야한다. 따라서 TABLE_PER_CLASS 전략은 실무에서 거의 사용되지 않는다.

삽입결과

부모 테이블인 ITEM 은 생성은 되나 삽입시 영향을 주지 않는다. 자식 테이블에만 삽입이 된다. 자식 테이블이 부모 테이블의 모든 컬럼을 갖는다.


[ 공통 속성 상속 ]

공통 속성

모든 엔티티가 id 와 name 을 갖는다고 하자. 엔티티가 100개 이렇게 된다면, id name 을 일일이 필드로 추가시키기는 번거롭다. 공통 속성을 BaseEntity 클래스로 만들어놓고 상속을 받을 수는 없을까?

BaseEntity

공통속성을 BaseEntity 로 빼고 @MappedSuperclass 어노테이션을 추가하였다. setter, getter 도 생성해놓을 수 있다.

공통속성 상속

공통속성을 사용할 클래스에서는 이를 상속받으면 자동으로 추가된다.

유의사항

@MappedSuperclass 는 상속관계 매핑과 관련 없으며, 공통 속성을 상속시킬 때 사용한다. 이 어노테이션이 추가된 클래스는 엔티티가 아니기에 테이블과 매핑되지 않으며, 해당 클래스로 em.find 연산도 불가능하다. BaseEntity 는 직접 객체를 사용할 일이 없으니 추상 클래스로 생성하자.


[ 정리 ]

상속관계의 매핑에는 조인전략, 단일테이블 전략, 각각테이블 전략 세가지가 있다.
객체와 잘맞고, 저장공간을 효율적으로 쓰는 조인전략을 기본으로 사용하자.
단순한 경우 단일테이블 전략을 쓰자. null 이 많아지지만 조인이 없어 조회가 더 빠르다.
각각테이블 전략은 부모속성 조회시 느리고, 유연하지 못해 사용하지 않는다.
@MapperSuperclass 로 공통속성을 빼서 상속시켜줄 수 있다.

post-custom-banner

0개의 댓글