JPA #5 상속관계 매핑

함형주·2022년 10월 30일
0

JPA

목록 보기
5/7
post-thumbnail

질문, 피드백 등 모든 댓글 환영합니다.

관계형 데이터베이스와 객체간의 차이점 중 하나가 상속 입니다.
객체는 명확히 상속을 지원하지만 RDB에서는 이를 슈퍼-서브 타입(Extended ER)으로 풀어 사용합니다.

슈퍼-서브 타입을 구현하는 방법은 3가지가 있는데 JPA에서 상속관계를 어떻게 매핑하는지 알아보겠습니다.

@Inheritance

부모 클래스에 @Inheritance을 이용하여 상속관계를 매핑할 수 있습니다.
상속의 기능 자체를 지원하는 것은 아니고 상속관계의 엔티티의 필드를 슈퍼-서브 타입 테이블에 매핑합니다.

InheritanceType.SINGLE_TABLE (default)

SINGLE_TABLE 전략은 부모와 자식 엔티티의 필드를 하나의 테이블에 모두 매핑하는 전략입니다.

장점으론 한 테이블에 모든 필드가 존재하므로 join이 필요없어 성능이 빠르고 SQL 쿼리가 단순합니다.

단점으로는 사용하지 않는 필드에는 null 로 채워지게 되고 한 테이블의 규모가 너무 커질 수 있습니다.

InheritanceType.TABLE_PER_CLASS

TABLE_PER_CLASS 전략은 구현 클래스마다 1:1로 매핑되는 테이블을 사용하는 전략입니다.

장점으론 not null 조건을 사용할 수 있고 서브 타입을 명확하게 표현할 수 있습니다.

단점으론 자식테이블을 조회할 때 UNION SQL를 사용하여 성능이 느립니다. 또한 자식 테이블을 통합한 쿼리를 생성하기 어렵습니다.

예를 들어 super_colunm을 pk로 사용할 경우 pk가 명확하지 않아 sub1, 2, 3의 모든 테이블을 조회한 후 이를 객체에 맞춰야 하므로 필연적으로 성능 이슈가 발생합니다.

때문에 이 방법은 굳이 사용하지 않는 것이 좋습니다.

InheritanceType.JOINED

JOINED 전략은 부모 엔티티와 자식엔티티를 각각의 테이블에 매핑하고 필요 시 join하여 사용합니다.

장점으론 테이블 정규화, 참조 무결성 제약조건 활용 가능, 저장 공간 효율화 등이 있습니다.

단점으론 join을 필수적으로 사용하기에 SQL 쿼리가 복잡하고 성능이 다소 느릴 수 있습니다. 또한 insert 쿼리나 update 쿼리 또한 여러 번 발생합니다.

이 방법을 일반적으로 가장 많이 사용합니다. 서비스에 따라선 SINGLE_TABLE을 활용하는 경우도 있지만 JOINED 전략이 주는 장점이 크기에 기본적으로 이 전략을 기본으로 사용하는 것이 좋습니다.

@DiscriminatorColumn

부모 클래스에서 사용되어 자식 클래스를 구분하기 위한 컬럼을 생성합니다. 기본 값으로 "DTYPE"을 컬럼명으로 사용합니다. InheritanceType.JOINED 전략 선택 시 사용합니다.

하이버네이트를 구현체로 사용할 경우 @DiscriminatorColumn를 사용하지 않을 경우 해당 컬럼을 생성하지 않습니다. 물론 join을 통해서 하위 테이블이 무엇인지 알 수 있지만 DB를 볼 때 DTYPE이 있어야 명확하게 파악이 가능하므로 사용하는 것을 추천합니다.

@DiscriminatorValue

자식 클래스에서 사용되어 엔티티를 저장할 때 @DiscriminatorColumn에서 지정한 컬럼에 저장할 값을 지정합니다. 기본 값으로 해당 클래스의 이름을 사용합니다.

profile
평범한 대학생의 공부 일기?

0개의 댓글