상속 관계 매핑은 엔티티 간의 상속 관계를 데이터베이스에 표현할 필요가 있을 때 사용하는 모델링 기법이다. 이는 객체지향의 상속 개념과 유사하게, 엔티티가 is-a 관계를 가지거나 부모 타입으로 일관되게 관리되어야 할 때 유용하다. RDBMS는 상속 개념을 직접 지원하지 않으므로 Super-Type Sub-Type Relationship이라는 기법으로 이를 대체한다.
상속관계 매핑이란?
- 필요성
- 엔티티 간 상속 관계가 필요한 경우가 존재한다.
- is-a 관계: 특정 엔티티가 다른 엔티티의 특성을 물려받을 때
- 부모 타입으로 일관된 관리: 여러 엔티티를 공통 부모 타입으로 관리해야 할 경우 - 부모 타입으로 다형적 쿼리(ex: 부모 타입으로 전부 조회)를 지원해야 할 경우
- 엔티티 간 상속 관계가 필요한 경우가 존재한다.
- 대체 기법
- RDBMS는 상속 개념이 없으므로, 슈퍼타입-서브타입 관계를 사용해 상속 개념을 구현한다.
- 모델링 기법
- 부모(슈퍼타입)와 자식(서브타입) 간의 관계를 명확히 하여, 객체 상속의 구조와 데이터베이스의 슈퍼타입-서브타입 관계를 매핑한다.
상속관계 매핑 전략
상속관계 매핑 전략은 슈퍼타입-서브타입 논리 모델을 실제 물리 모델로 구현하는 방법을 의미한다. 대표적인 전략은 다음과 같다.
조인 전략
- 정의: 각 엔티티를 별도의 테이블로 변환한 후, 조인을 통해 전체 데이터를 구성하는 방식이다.
- 특징
- 각각의 엔티티가 개별 테이블로 분리되어 관리된다.
- Super class는 추상 클래스로 구현하는 것이 권장된다.
- 정규화된 테이블 구조로 DBA들이 선호한다.
- 장점
- 테이블이 정규화되어 있으며, 외래 키 참조 무결성 제약조건을 활용할 수 있다.
- 설계가 깔끔하며 저장공간 효율이 높다.
- 단점
- 조회 시 다수의 조인이 필요해 성능 저하가 발생할 수 있다.
- 조회 쿼리가 복잡해지고, 데이터 저장 시 INSERT SQL이 2번 호출된다.
단일 테이블 전략
- 정의: 모든 엔티티를 하나의 통합 테이블로 구성하는 방식으로, JPA에서 기본적으로 선택하는 전략이다.
- 특징
- Super class는 추상 클래스로 구현하는 것이 바람직하다.
- 장점
- 조인이 필요 없으므로 조회 성능이 빠르고, 쿼리가 단순하다.
- 단점
- 자식 엔티티에 매핑된 컬럼은 모두 null을 허용해야 한다.
- 이는 자식 입장에서 자신의 컬럼이 아닌 데이터가 null로 채워져야 함을 의미한다.
- 모든 데이터를 하나의 테이블에 저장하기 때문에 테이블이 커질 수 있으며, 상황에 따라 조회 성능이 저하될 수 있다.
- 자식 엔티티에 매핑된 컬럼은 모두 null을 허용해야 한다.
구현 클래스마다 테이블 전략
- 정의: 각 서브타입을 별도의 테이블로 변환하는 방식이다.
- 특징 및 장점
- 서브타입을 명확하게 구분해 처리할 수 있으며, not null 제약조건을 적용할 수 있다.
- 단점
- 여러 자식 테이블을 함께 조회할 때 UNION SQL이 필요해 성능이 떨어진다.
- 자식 테이블을 통합하여 쿼리하기 어려워 사용이 권장되지 않는다.
전략 설정 방법
엔티티 상속 관계를 구현할 때는 부모와 자식 엔티티에 각각 적절한 어노테이션을 적용한다.
- 부모 엔티티
- @Inheritance(strategy=InheritanceType.XXX)를 사용해 상속 전략을 지정한다.
- JOINED: 조인 전략
- SINGLE_TABLE: 단일 테이블 전략
- TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
- @DiscriminatorColumn(name="DTYPE") 어노테이션을 추가하여, 상속 관계를 구분할 수 있는 DTYPE 컬럼을 생성한다.
- 이 어노테이션이 있어야 DTYPE 컬럼이 생성되며, 기본 이름은 DTYPE이다.
- @Inheritance(strategy=InheritanceType.XXX)를 사용해 상속 전략을 지정한다.
- 자식 엔티티
- @DiscriminatorValue("XXX") 어노테이션을 사용해, DTYPE 컬럼에 저장될 값을 지정한다.
- 기본값은 엔티티 클래스 이름이다.
- @DiscriminatorValue("XXX") 어노테이션을 사용해, DTYPE 컬럼에 저장될 값을 지정한다.
@MappedSuperclass와의 차이
@MappedSuperclass를 사용할 경우, 부모 클래스는 테이블로 생성되지 않는다. 이는 상속 관계 매핑과 달리, 단순히 공통 속성을 제공하는 용도로 사용된다. 단순히 공통 필드와 매핑 정보를 재사용하고자 할 때 사용하며, 부모 타입에 대한 독립적 관리 혹은 다형적 쿼리에는 사용하지 않는다.
엔티티의 상속 관계 매핑은 각 애플리케이션의 요구 사항과 데이터베이스 설계 원칙에 맞추어 적절한 전략을 선택해야 한다. 각 전략의 장단점을 면밀히 검토하여, 데이터 저장 및 조회 성능, 테이블 정규화, 관리 용이성 등을 고려한 결정이 필요하다.
출처: 자바 ORM 표즌 JPA 프로그래밍