상속관계 맵핑
객체지향의 상속
이라는 개념은 RDB에는 없고 Super Type / Sub Type 관계
라는 모델링 기법이 가장 유사해 상속관계를 이 Super/Sub type
관계로 맵핑하는 방법으로는 크게 3가지가 존재한다.
1. 조인 전략
테이블을 각각 만들고 조회할때 조인을 사용하는 방법
부모클래스에 @Inheritance(strategy = InheritanceType.JOINED)
를 통해 부모클래스임을 명시하고 맵핑전략을 지정해주어야 한다. @DiscriminatorColumn(name = "DTYPE")
을 명시함으로써 자식 테이블을 구분하기 위한 DTYPE
필드를 지정한다.
자식 클래스
들은 @DiscriminationValue()
를 통해 엔티티를 저장할 때 구분 컬렘에 입력할 값을 지정할 수 있다. 자식클래스의 저장되는 PK이자 FK
는 부모 테이블의 ID명을 그대로 사용하는데 @PrimaryKeyJoinColumn
을 이용해 컬럼명을 변경할 수 있다.
특징
JPA 표준 명세는 구분 컬럼을 사용하도록 하지만 몇몇 구현체는 이 구분 컬럼이 없어도 동작한다.
장점
테이블이 정규화된다.
외래키 참조 무결정 제약조건을 활용할 수 있다.
저장공간을 효율적으로 사용한다.
단점
조회시 많은 조인으로 성능 저하 우려
복잡한 조회 쿼리
데이터를 등록할 Insert SQL을 두번 실행한다.
2. 단일 테이블 전략
테이블을 하나만 사용해 통합하는 방법으로 각 자식의 필드들와 부모 엔티티의 필드가 하나의 테이블로 합쳐진 방법이다. 그렇기 때문에 자식 엔티티가 매핑한 컬럼들은 모두 null
을 허용해야 하고 구분 컬럼(DiscriminatorValue)
을 필수로 사용해야 한다. (한개의 자식엔티티를 저장하려고 하면, 그 외의 자식 엔티티 필드값은 당연히 null이기 되기 때문에 null이 허용되어야 한다.)
부모 클래스에 Inheritance(strategy = InheritanceType.SINGLE_TYPE)
으로 지정하면 사용할 수 있다.
장점
조인이 필요없어 조회성능이 빠르다.
조회 쿼리가 단순하다.
단점
자식 엔티티가 맵핑한 컬럼들은 모두 null을 허용해야한다.
테이블의 크기가 커지기 때문에 오히려 성능이 느려질 수 있다.
3. 구현 클래스마다 테이블 전략
서브타입 마다 하나의 테이블을 만드는 방법으로 Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
를 지정하면 이 전략을 사용할 수 있다.
자식엔티티마다 테이블을 만드는 방법으로 구분 컬럼을 사용하지 않아도 되지만 일반적으로 추천하지 않는 방법이다.
장점
서브타입을 구분해서 처리할때 효과적
not null 을 사용할 수 있다.
단점
여러 자식 테이블을 함께 조회할때 성능이 느리다.
자식 테이블을 통합해서 쿼리하기 힘들다.
@MappedSuperclass
위의 3가지 전략은 부모/자식 클래스를 테이블과 맵핑했지만 @MappedSuperClass
는 부모 클래스를 실제 테이블과 맵핑하고 싶지 않을때 사용한다.
@AttributeOverrides
/@AttributeOverride
: 맵핑 정보(필드) 재정의 할때 사용@AssociationOverrides
: 연관관계 재정의 할 때 사용
Reference
자바 ORM 표준 JPA 프로그래밍 책 (김영한 저)
Last updated