본문 바로가기
개발공부 개발새발/DB

JPA) 상속관계 매핑 (여러 전략들과 @MappedSuperclass)

by 휴일이 2022. 11. 25.

 

 




관계형 DB는 상속 관계가 없으나
슈퍼타입 - 서브타입 관계는 상속 관계와 비슷하긴 해서
슈퍼타입 - 서브타입 관계를 자바에서 상속 관계로 구현한 것이 상속관계 매핑이다



구현 방법 세 가지
조인 전략 : 슈퍼, 서브타입을 각각 테이블로 만들어서 조인으로 불러오기
단일 테이블 전략 : 통합 테이블로(하나로 통합) 만들기
구현 클래스마다 테이블 전략 : 서브타입 테이블만 만들기



어노테이션
@Inheritance(strategy = Inheritance.Type.~~~)
Type 뒤에 무슨 전략을 쓸 건지 적어주면 됨
JOINED : 조인 전략
SINGLE_TABLE : 단일 테이블 전략
TABLE_PER_CLASS : 구현 클래스마다 테이블 전략

@DiscriminatorColumn(name=“DTYPE”) 
조인 전략을 쓸 때,
슈퍼 테이블에 서브 테이블을 구분할 수 있는 구분 컬럼을 추가하기 위해 쓴다
name = "컬럼명"
무조건 추가해주자 !

@DiscriminatorValue(“XXX”)
구분 컬럼을 추가했는데,
엔티티 이름으로 구분하는 것이 아닌
새 이름을 쓰고 싶을 때 사용
(이 엔티티는 DTYPE에 이 이름으로 저장되게 해줘~)




조인 전략(기본으로 깔고 가기)
*장점
- 테이블 정규화 (많이 써용)
- 외래 키만 참조하면 값을 가져올 수 있다
- 저장 공간이 효율적이다(나눠서 담으니)

*단점
- INSERT가 두 번 들어가야 한다(슈퍼, 서브)
- 조회 쿼리도 복잡하다
- 조인도 많이 사용해야 한다 
- 결과적으로 성능이 떨어진다(그래도 대부분 신경쓸만큼은 아닌듯?)




단일 테이블 전략(복잡한 비즈니스를 할 경우)
* 장점
- 조인이 필요 없으니, 조회 성능이 좋다
- 조회 쿼리가 단순하다

* 단점
- 자식 엔티티가 값을 넣지 않은 컬럼은 무조건 null이다
- 단일 테이블에 모든 걸 저장해서 테이블이 커질 수 있음
- 상황에 따라서 오히려 조회 성능이 떨어질 수도 있다




구현 클래스마다 테이블 전략(XX이거 쓰지마세연XX)
* 장점
- 서브 타입을 명확하게 구분해야할 경우 좋다
- not null도 사용 가능!

* 단점
- 여러 자식 테이블을 함께 조회할 때에 성능이 매우 느림(UNION으로 다 뒤져야됨)
- 자식 테이블 통합 쿼리가 어려움
- 테이블이 늘어나고 수정될 수록 감당이 안 됨
- 걍 쓰지 마세여~

 

 

 

 

@MappedSuperclass
!추상 클래스로 쓰쟈!

공통 매핑 정보가 필요할 때 사용
- 중복 정보인데(id, name..)
- 얘 맨날 엔티티 만들때마다 만들기 귀차나~
- 속성만 쓰고 싶어ㅠㅠ
- DB는 아예 따로임(관련 X) 그냥 객체에서 씁니다요
- 테이블은 생성 안 됨XXX 속성만 가져옴

1. 공통 매핑 정보 클래스를 상속받고
2. 공통 매핑 정보 클래스에 @MappedSuperclass 어노테이션 붙인다
3. 그러면 테이블을 생성하거나 수정할 때 이 속성도 자동으로 들어감
4. 슈퍼 타입에 상속해두면, 서브 타입도 같이 받기 때문에 개이득



@MappedSuperclass 클래스에 있는 속성에
@Column(name = "컬럼명") 해두면
속성명이 아닌 지정 이름이 컬럼명으로 생성됩니다


@MappedSuperclass

package jpabook.jpashop.domain;

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

@MappedSuperclass
public abstract class BaseEntity {

    private String createdBy;
    private LocalDateTime createdDate;
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;

    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 String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public LocalDateTime getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(LocalDateTime lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}

 

@MappedSuperclass 클래스를 상속 받은 매핑

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item extends BaseEntity {

 

 

Item(슈퍼타입)를 상속받은 서브타입

@Entity
public class Movie extends Item {

 

 

 

 

728x90