상속관계매핑(객체의 상속관계를 어떻게 DB에 매핑하는지)

 

원래 관계형 DB는 상속관계라는것이 없다. 대신 이와 유사하게 슈퍼타입-서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.

상속관계 매핑이란 (객체의 상속구조) - (Db의 슈퍼타입-서브타입 관계)를 매핑

 

DB의 슈퍼타입-서브타입 관계 / 객체의 상속구조

 

슈퍼타입-서브타입 논리모델을 실제 물리모델로 구현하는 방법은 총 3가지가 있다.

1. 각 테이블로 변환 -> join전략

객체 상속관계 / DB

오른쪽에 DB를 보면 ITEM_ID를 통해 Join을통해 필요하면 조회하는 방식.

이런방식은 item,(album/movie/book) 에 insert를 각가해줘야하고 

ITEM_ID라는 개인키를통해 join 해서 조회를 한다.

 

item이 앨범인지 북인지 영화인지 구분하기위해 DTYPE을 통해 구분한다.

 

장점:

- 테이블이 정규화되어있다.

- 외래키 참조 무결성 제약조건 활용가능 -> item_id를 통해 다른 테이블 접근이 가능하므로 item테이블만으로 조회가 가능. 

- 저장공간 효율화

 

단점

- 조회시 조인을 많이사용(성능저하)

- 조회 쿼리가 복잡

- 데이터 저장시 insert sql이 2번 호출

 

 

2. 통합 테이블로 변환 -> 단일 테이블 전략

 

 

하나의 테이블로 합쳐버린다. 

item이 앨범인지 북인지 영화인지 구분하기위해 DTYPE을 통해 구분한다.

 

장점

- 조인 필요없어서 조회성능이 빠르다.

- 조회 쿼리가 단순

 

단점

- 자식 Entity가 매핑한 컬럼은 모두 null 허용

- 모든것을 하나의 테이블로 저장해서 테이블이 커진다.

 

 

3. 서브타입 테이블로 변환 -> 구현클래스마다 테이블 전략

 

추상방식이 아닌 구현클래스 마다 각각 나누어서 DB 설계를 한다. 

 

결론부터 말하면 이건 쓰면 안된다!!! (DB설계자 와 ORM 전문가 둘다 추천하지않는다.)

장점

- 서브타입을 명확히 구분해서 처리할떄 효과적

- not null 제약조건 사용가능

단점

- 여러 자식테이블을 함께 조회할떄 성능이 느림(Union sql)

- 자식테이블을 통합해서 쿼리하기가 어려움.

 

 

DB설계시 1,2,3방법중 어떤 방법을 사용하든 객체와 매핑이 가능하다.!!! 

 

ITEM 클래스  

@Entity 
(JPA는 기본적략이 2번 단일테이블 전략이다)
(join이나 insert가 부모,자식에 각각 들어가는상황같은게 없어서
성능이 가장 잘나온다.)
1번
@Entity

@Inheritance(strategy=InheritanceType.JOINED)
부모 클래스(Item)에서 사용
@Entity
@DiscriminatorColumn
참고: name 속성으로 칼럼명 Dtype말고 다른걸로 바꿀수있다. 

자식클래스(Movie)에서 사용
@Entity
@DiscriminatorValue("M")

Dtype이 컬럼으로 자동으로 추가된다.


Movie말고 M 으로 바꾸고싶으면 DiscriminatorValue 사용

3번
@Entity
@Inheritance(strategy= InheritanceType.TABLE_PER_CLASS)
이것을 사용할떄 abstract class Item으로 추상클래스로 만들고 사용.

Item테이블이 안만들어지고 Movie, Album, Book각각 만들어짐. 

 

 

 

 

 

 

@MappedSuperClass

 

- 테이블과 관계없고 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할

객체입장에서 생각하면 id, name이 중복된게 계속해서 나오면 부모클래스로 두고 상속해서 쓰고싶어진다.

MappedSuperclass을 써서 속성만 상속해서 사용할수있다. (DB는 구조상 변화없음)

 

 

 

package hellojpa;

import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@MappedSuperclass
public abstract class BaseEntity {
    private String createdBy;
    private LocalDateTime createdDate;

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public LocalDateTime getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(LocalDateTime createdDate) {
        this.createdDate = createdDate;
    }
}

public class Team extend BaseEntity {}
public class Member extend BaseEntity {}

member, team 에서 BaseEntity의 속성들만 상속받아서 사용할떄 주로 사용.(DB에는 각각 createBy, createDate를 갖고있다.)

 

- 주의: 상속관계 매핑이 아니라서 테이블과 매핑 안됨, 엔티티가 아니라서 조회,검색같은게 안된다. (em.find(BaseEntity) 이런거 사용불가)

- 직접 생성해서 사용할일 없어서 추상클래스에 사용 권장.

- 부모클래스를 상속받는 자식클래스에 매핑정보만 제공!

- 주로 등록일,수정일,등록자,수정자같은 전체 엔티티에서 공통으로 적용하는 정보를 모을떄 사용. 

- 참고: @Entity 클래스는 @Entity/@MappedSuperclass가 붙은 클래스만 상속가능!

 

 
 
 
 
 
 

'𝗦𝗣𝗥𝗜𝗡𝗚 > 𝐎𝗥𝗠-𝗝𝗣𝐀' 카테고리의 다른 글

다양한 연관관계 매핑  (0) 2024.01.03
연관관계 매핑 기초  (0) 2024.01.03
엔티티 매핑  (0) 2024.01.02
JPA 영속성 컨텍스트  (0) 2023.12.27
JPA 구동방식  (0) 2023.12.27