# Chapter 7: 고급 매핑

<br>

## 1. 상속 관계 매핑

* 관계형 데이터베이스는 `상속` 이라는 개념이 없다
  * 대신에 `Super-Type Sub-Type` 관계라는 모델링 기법이 객체의 상속 개념과 가장 유사하다
  * ORM에서 이야기하는 상속 관계 매핑은 객체의 `상속 구조`와 데이터베이스의 `슈퍼타입 서브타입 관계`를 `매핑`하는 것이다
* 슈퍼타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현하는 방법 3가지
  1. 각각의 테이블로 변환
     * 각각을 모두 테이블로 만들고 조회할 때 조인을 사용
     * JPA에서는 `조인 전략`이라 한다
  2. 통합 테이블로 변환
     * 테이블을 하나만 사용해서 통합
     * JPA에서는 `단일 테이블 전략`이라 한다
  3. 서브 타입 테이블로 변환
     * 서브 타입마다 하나의 테이블을 만든다
     * JPA에서는 `구현 클래스마다 테이블 전략` 이라 한다

### 1-1. 조인 전략

* 엔티티 각각을 모두 테이블로 만들고, 자식 테이블이 부모 테이블의 `기본 키` 를 받아서 `기본 키 + 외래 키` 로 사용하는 전략
  * 조회할 때 JOIN을 자주 사용!
* `주의할 점`
  * 객체는 타입으로 구분할 수 있지만, 테이블은 타입의 개념이 없다
    * 따라서 타입을 구분하는 칼럼을 추가해야 한다!
* `장점`
  * 테이블이 `정규화`된다
  * 외래 키 참조 무결성 제약조건을 활용할 수 있다
  * 저장공간을 효율적으로 사용한다
* `단점`
  * 조회할 때 조인이 많이 사용되므로 성능이 저하될 수 있다
  * 조회 쿼리가 복잡하다
  * 데이터를 등록할 INSERT SQL을 두 번 실행한다
* `특징`
  * 하이버네이트를 포함한 몇몇 구현체는 구분 컬럼 없이도 동작한다

### 1-2. 단일 테이블 전략

* 이름 그대로 테이블을 하나만 사용하고, `구분 컬럼`으로 어떤 자식 데이터가 저장되었는지 구분
  * 조회할 때 조인을 사용하지 않으므로 일반적으로 가장 빠름!
* `주의할 점`
  * 자식 엔티티가 매핑한 컬럼은 모두 `null을 허용` 한다는 점
* `장점`
  * 조인이 필요 없으므로 일바넞긍로 조회 성능이 빠르다
  * 조회 쿼리가 단순하다
* `단점`
  * 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다
  * 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다
    * 상황에 따라서는 조회 성능이 오히려 느려질 수 있따
* `특징`
  * 구분 컬럼을 꼭 사용해야 한다!
    * `@DiscriminatorColumn` 설정 필수!
  * `@DiscriminatorColumn` 을 지정하지 않으면 기본으로 `엔티티 이름` 을 사용한다

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

* 자식 엔티티마다 테이블을 만든다
  * 자식 테이블에 각각 필요한 칼럼이 모두 있다
  * 일반적으로 추천하지 않는 전략!
* `장점`
  * 서브 타입을 구분해서 처리할 때 효과적
  * not null 제약 조건 사용 가능
* `단점`
  * 여러 자식 테이블을 함께 조회할 때 성능이 느리다
    * SQL에 UNION을 사용해야 한다
  * 자식 테이블을 통합해서 쿼리하기 어렵다
* `특징`
  * 구분 컬럼을 사용하지 않는다

## 2. `@MappedSuperClass`

* 부모 클래스는 테이블과 매핑하지 않고, 부모 클래스를 상속 받는 자식 클래스에게 매핑 정보만 제공하고 싶으면 `@MappedSuperClass` 를 사용하면 된다
* `@MappedSuperClass` 는 추상 클래스와 비슷한데, `@Entity` 는 실제 테이블과 매핑되지만 `@MappedSuperClass` 는 실제 테이블과 매핑되지 않는다
  * 단순히 매핑 정보를 상속할 목적으로만 사용된다
* 테이블과는 관계가 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모아주는 역할을 한다
* `@MappedSuperClass` 를 사용하면 등록 일자, 수정 일자, 등록자, 수정자와 같은 여러 엔티티에서 공통으로 사용하는 속성을 효괒거으로 관리할 수 있따

## 3. 복합 키와 식별 관계 매핑

### 3-1. 식별 관계 vs 비식별 관계

* 식별 관계
  * 부모 테이블의 기본 키를 내려받아서 자식 테이블의 기본 키 + 외래 키로 사용하는 관계
* 비식별 관계
  * 부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계
  * `필수적 비식별 관계`
    * 외래 키에 NULL을 허용하지 않음
    * 연관관계를 필수적으로 맺어야 함
  * `선택적 비식별 관계`
    * 외래 키에 NULL을 허용함
    * 연관관계를 맺을지 말지 선택할 수 있음

### 3-2. 복합 키: 비식별 관계 매핑

* JPA에서 식별자를 둘 이상 사용하려면, 별도의 식별자 클래스를 만들어야 한다
* JPA는 복합 키를 지원하기 위해 `@IdClass` 와 `@EmbeddedId` 2가지 방법을 제공한다
* `@IdClass`
  * 식별자 클래스의 조건
    * 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 한다
    * `Serializable` 인터페이스를 구현해야 한다
    * equals, hashcode를 구현해야 한다
    * 기본 생성자가 있어야 한다
    * 식별자 클래스는 public이어야 한다
* `@EmbeddedId`
  * 식별자 클래스에 기본키를 직접 매핑한다
  * 식별자 클래스의 조건
    * `@Embeddable` 어노테이션을 붙여주어야 한다
    * `Serializable` 인터페이스를 구현해야 한다
    * equals, hashcode를 구현해야 한다
    * 기본 생성자가 있어야 한다
    * 식별자 클래스는 public이어야 한다
