# 상속관계 맵핑

객체지향의 `상속`이라는 개념은 RDB에는 없고 `Super Type / Sub Type 관계`라는 모델링 기법이 가장 유사해 상속관계를 이 `Super/Sub type`관계로 맵핑하는 방법으로는 크게 3가지가 존재한다.

## 1. 조인 전략

테이블을 각각 만들고 조회할때 조인을 사용하는 방법

부모클래스에 `@Inheritance(strategy = InheritanceType.JOINED)`를 통해 부모클래스임을 명시하고 맵핑전략을 지정해주어야 한다. `@DiscriminatorColumn(name = "DTYPE")`을 명시함으로써 자식 테이블을 구분하기 위한 `DTYPE` 필드를 지정한다.

`자식 클래스`들은 `@DiscriminationValue()`를 통해 엔티티를 저장할 때 구분 컬렘에 입력할 값을 지정할 수 있다. 자식클래스의 저장되는 `PK이자 FK`는 부모 테이블의 ID명을 그대로 사용하는데 `@PrimaryKeyJoinColumn`을 이용해 컬럼명을 변경할 수 있다.

## 특징

JPA 표준 명세는 구분 컬럼을 사용하도록 하지만 몇몇 구현체는 이 구분 컬럼이 없어도 동작한다.

### 장점

1. 테이블이 정규화된다.
2. 외래키 참조 무결정 제약조건을 활용할 수 있다.
3. 저장공간을 효율적으로 사용한다.

### 단점

1. 조회시 많은 조인으로 성능 저하 우려
2. 복잡한 조회 쿼리
3. 데이터를 등록할 Insert SQL을 두번 실행한다.

\
\


## 2. 단일 테이블 전략

테이블을 하나만 사용해 통합하는 방법으로 각 자식의 필드들와 부모 엔티티의 필드가 하나의 테이블로 합쳐진 방법이다. 그렇기 때문에 자식 엔티티가 매핑한 컬럼들은 모두 `null`을 허용해야 하고 `구분 컬럼(DiscriminatorValue)`을 필수로 사용해야 한다. (한개의 자식엔티티를 저장하려고 하면, 그 외의 자식 엔티티 필드값은 당연히 null이기 되기 때문에 null이 허용되어야 한다.)

부모 클래스에 `Inheritance(strategy = InheritanceType.SINGLE_TYPE)`으로 지정하면 사용할 수 있다.

## 장점

1. 조인이 필요없어 조회성능이 빠르다.
2. 조회 쿼리가 단순하다.

## 단점

1. 자식 엔티티가 맵핑한 컬럼들은 모두 null을 허용해야한다.
2. 테이블의 크기가 커지기 때문에 오히려 성능이 느려질 수 있다.

\
\


## 3. 구현 클래스마다 테이블 전략

서브타입 마다 하나의 테이블을 만드는 방법으로 `Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)`를 지정하면 이 전략을 사용할 수 있다.

자식엔티티마다 테이블을 만드는 방법으로 구분 컬럼을 사용하지 않아도 되지만 일반적으로 추천하지 않는 방법이다.

## 장점

1. 서브타입을 구분해서 처리할때 효과적
2. not null 을 사용할 수 있다.

## 단점

1. 여러 자식 테이블을 함께 조회할때 성능이 느리다.
2. 자식 테이블을 통합해서 쿼리하기 힘들다.

## @MappedSuperclass

위의 3가지 전략은 부모/자식 클래스를 테이블과 맵핑했지만 `@MappedSuperClass`는 부모 클래스를 실제 테이블과 맵핑하고 싶지 않을때 사용한다.

* `@AttributeOverrides` / `@AttributeOverride` : 맵핑 정보(필드) 재정의 할때 사용
* `@AssociationOverrides` : 연관관계 재정의 할 때 사용

\
\
\


***

## Reference

자바 ORM 표준 JPA 프로그래밍 책 (김영한 저)
