1. 상속 관계 매핑
객체의 상속과 DB의 슈퍼타입 서브타입 관계를 매핑하는 것
- 관계형 데이터베이스에는 객체지향 언어에서 다루는 상속이라는 개념이 없다.
- 대신 슈퍼타입 서브타입 관계(Super-Type Sub-Type Relationship)이라는 모델링 기법이 객체의 상속 개념과 가장 유사하다.
- 슈퍼타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현할 때는 3가지 방법을 선택할 수 있다.
- 각각 테이블로 변환 -> 조인 전략
- 통합 테이블로 변환 -> 단일 테이블 전략
- 서브타입 테이블로 변화 -> 구현 클래스마다 테이블 전략
2. 조인 전략
- 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다.
- 조회할 때 조인을 사용해야 한다.
- 객체는 타입으로 구분할 수 있지만 테이블은 타입의 개념이 없다.
- 타입을 구분하는 컬럼을 추가해야 한다. (DTYPE)
@Entity
@Getter @Setter
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {
private String artist;
}
@Entity
@DiscriminatorValue("B")
@Getter @Setter
public class Book extends Item{
private String author;
private String isbn;
}
@Entity
@DiscriminatorValue("M")
@Getter @Setter
public class Movie extends Item{
private String director;
private String actor;
}
(1) @Inheritance(strategy = InheritanceType.JOINED)
- 상속 매핑은 부모 클래스에 @Inheritance를 사용해야 한다.
- 그리고 매핑 전략을 지정해야 한다. 조인 전략을 사용하기 위해 InheritanceType.JOINED를 사용했다.
(2) @DiscriminatorColumn(name = "DTYPE")
- 부모 클래스에 구분 컬럼을 지정한다.
- 이 컬럼으로 저장된 자식 테이블을 구분할 수 있다.
- 기본 값이 DTYPE이다.
(3) @DiscriminatorValue("M")
- 엔티티를 저장할 때 구분 컬럼에 입력할 값을 지정한다.
- 만약 영화 엔티티를 저장하면 구분 컬럼인 DTYPE에 값 M이 저장된다.
(4) 장점과 단점
- 장점
- 테이블이 정규화된다.
- 외래 키 참조 무결성 제약조건을 활용할 수 있다.
- 저장공간을 효율적으로 사용한다
- 단점
- 조회할 때 조인이 많이 사용되므로 성능이 저하될 수 있다.
- 조회 쿼리가 복잡하다.
- 테이터를 등록할 INSERT SQL을 두 번 실행한다.
3. 단일 테이블 전략
- 테이블을 하나만 사용한다.
- 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
- Book 엔티티를 저장하면 ITEM 테이블의 AUTHOR, ISBN 컬럼만 사용하고 다른 엔티티와 매핑된 컬럼은 사용하지 않으므로 null이 입력된다.
@Entity
@Getter @Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {
private String artist;
}
@Entity
@DiscriminatorValue("B")
@Getter @Setter
public class Book extends Item{
private String author;
private String isbn;
}
@Entity
@DiscriminatorValue("M")
@Getter @Setter
public class Movie extends Item{
private String director;
private String actor;
}
- InheritanceType.SINGLE_TABLE로 지정하면 단일 테이블 전략을 사용한다.
- 테이블 하나에 모든 것을 통합하므로 구분 컬럼을 필수로 사용해야 한다.
- 장점
- 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
- 조회 쿼리가 단순하다.
- 단점
- 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서는 조회 성능이 오히려 느려질 수 있다.
- 특징
- 구분 컬럼을 꼭 사용해야 한다. @DiscriminatorColumn을 설정해야 한다.
- @DiscriminatorValue를 지정하지 않으면 기본으로 엔티티 이름을 사용한다.
- ex) Movie, Album, Book
4. 구현 클래스마다 테이블 전략
- 장점
- 서브 타입을 명확하게 구분해서 처리할 때 효과적이다
- not null 제약조건 사용할 수 있다.
- 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다(UNION SQL 필요)
- 자식 테이블을 통합해서 쿼리하기 어렵다.
- 이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천하지 않는 전략이다.
- 조인이나 단일 테이블 전략을 사용하자.
반응형
'JPA > JPA' 카테고리의 다른 글
[JPA] 프록시 (Proxy) (0) | 2022.01.03 |
---|---|
[JPA] @MappedSuperclass (0) | 2022.01.03 |
[JPA] 연관관계 매핑 - 2 (0) | 2022.01.02 |
[JPA] 연관관계 매핑 - 1 (0) | 2022.01.01 |
[JPA] 엔티티 매핑 (Entity Mapping) (0) | 2021.12.31 |
댓글