상속관계 매핑
Contents
상속관계 매핑
객체는 상속관계가 존재하지만, 관계형 데이터베이스는 상속 관계가 없다. 그나마 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다. 상속관계 매핑이라는 것은 객체의 상속 구조와 DB의 슈퍼타입 서브타입 관계를 매핑하는 것이다.
DB의 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법은 세가지 있다. DB입장에서 세가지로 구현하지만 JPA에서는 어떤 방식을 선택하던 매핑이 가능하다.
주요 어노테이션
@Inheritance(strategy=InheritanceType.XXX)
JPA가 DB의 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 세가지 방식과 매핑하려면 @Inheritance(strategy=InheritanceType.XXX)
의 stategy를 설정해주면 된다. default 전략은 SINGLE_TABLE(단일 테이블 전략)이다.
InheritanceType 종류는 다음과 같다.
- JOINED : 조인 전략, 각각 테이블로 변환
- SINGLE_TABLE : 단일 테이블 전략, 통합 테이블로 변환
- TABLE_PER_CLASS : 구현 클래스마다 테이블 전략, 서브타입 테이블로 변환
@DiscriminatorColumn(name=“DTYPE”)
부모 클래스명 상단에 선언한다. 하위 클래스를 구분하는 용도의 컬럼이다. 관례는 default = DTYPE
@DiscriminatorValue(“XXX”)
하위 클래스명 상단에 선언한다. 엔티티를 저장할 때 슈퍼타입의 구분(DTYPE) 컬럼에 저장할 값을 지정한다. 어노테이션을 선언하지 않을 경우 기본값으로 클래스 이름이 들어간다.
상속관계 매핑 전략
조인 전략(@Inheritance(strategy = InheritanceType.JOINED))
- 장점
- 테이블이 정규화가 되어있고, 외래 키 참조 무결성 제약조건 활용 가능
- ITEM의 PK가 ALBUM, MOVIE, BOOK의 PK이자 FK이다. 그래서 다른 테이블에서 아이템 테이블만 바라보도록 설계하는 것이 가능하다.
- 저장공간 효율화
- 테이블 정규화로 저장공간이 딱 필요한 만큼 소비된다.
- 테이블이 정규화가 되어있고, 외래 키 참조 무결성 제약조건 활용 가능
- 단점
- 조회시 조인을 많이 사용하므로 단일 테이블 전략에 비하면 성능이 안 나온다.
- 조회 쿼리가 복잡하다.
- 데이터 저장시에 INSERT 쿼리가 상위, 하위 테이블 두번 발생한다.
- 정리
- 성능 저하라고 되어있지만, 실제로는 영향이 크지 않다.
- 오히려 저장공간이 효율화 되기 때문에 장점이 크다.
- 기본적으로는 조인 정략이 정석이라고 보면 된다. 객체랑도 잘 맞고, 정규화도 되고, 그래서 설계가 깔끔하게 나온다.
단일 테이블 전략
- 장점
- 조인이 필요 없으므로 일반적인 조회 성능이 빠르다.
- 조회 쿼리가 단순하다.
- 단점
- 자식 엔티티가 매핑한 컬럼은 모두 NULL을 허용해야 한다.
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.
- 상황에 따라서 조인 전략보다 성능이 오히려 느려질 수 있다. 그러나 보통 이 상황에 해당하는 임계점을 넘을 일은 많지 않다.
구현 클래스마다 테이블 전략
- 장점
- 서브 타입을 명확하게 구분해서 처리할 때 효과적이다
- NOT NULL 제약조건을 사용할 수 있다.
- 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다(UNION SQL)
- 자식 테이블을 통합해서 쿼리하기 어렵다.
- 변경이라는 관점으로 접근할 때 굉장히 좋지 않다.
- 정리
- ORM을 하다보면 데이터 쪽과 객체 쪽에서 trade off를 할 때가 있는데, 이 전략은 두 쪽 모두에서 추천하지 않는다.
정리
기본적으로는 조인 전략을 선택한다. 그리고 조인 전략과 단일 테이블 전략의 trade off를 생각해서 전략을 선택한다.
굉장히 심플하고 확장의 가능성도 적으면 단일 테이블 전략을 선택한다. 그러나 비즈니스 적으로 중요하고, 복잡하고, 확장될 확률이 높으면 조인 전략을 선택한다.