[스프링 JPA] - 상속관계 매핑

sonnng·2023년 9월 30일
0

Spring

목록 보기
14/41

목차

  1. 상속관계 매핑

  2. @MappedSuperclass

1. 상속관계 매핑

  • 객체에는 상속관계가 있으나, 관계형 데이터베이스는 상속관계가 없다.

  • 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.

  • 슈퍼타입 서브타입 논리모델 -> 물리모델로 구현하는 방법
    @Inheritance(strategy=InheritanceType.XXX) 를 활용
    • JOINED: 조인 전략
    • SINGLE_TABLE: 단일 테이블 전략
    • TABLE_PER_CLASS: 구현 클래스마다 테이블 전략

    #### 1 ) (추천)(정석)(복잡)각각 테이블로 변환 = 조인전략을 사용<br/>
    : <br/>
    [방법]상속관계에서 가장 부모인 객체에 `@Inheritance(strategy=InheritanceType.JOINED)` 작성<br/>
    :<br/>
    [쿼리문] 값을 넣으면 부모 테이블의 ID값이 자식 테이블의 ID값에 FK, PK로 들어가게 된다. 즉 INSERT 쿼리문 2회<br/>
    :<br/>
    [조회쿼리문]`em.persist(movie); em.flush(); em.clear();` 하고 나서 `em.find(Movie.class, movie);` 를 하면 inner join 쿼리가 날아간다. 즉 join 쿼리문 1회가 필요하게 된다.
    <br/>
    :<br/>
    [장점] 저장공간 효율화/외래키 참조 무결성 제약조건 활용을 통해 한번에 조회가능
    [단점] 복잡해질수록 성능 저하/조회쿼리 복잡해짐/데이터 저장시 INSERT SQL 2번 호출 <br/>
    
    ```java
    Hibernate: 
        /* insert jpabook.Movie
            */ insert 
            into
                Item
                (name, price, ITEM_ID) 
            values
                (?, ?, ?)
    Hibernate: 
        /* insert jpabook.Movie
            */ insert 
            into
                Movie
                (actor, director, ITEM_ID) 
            values
                (?, ?, ?)
    Hibernate: 
        select
            movie0_.ITEM_ID as ITEM_ID1_5_0_,
            movie0_1_.name as name2_5_0_,
            movie0_1_.price as price3_5_0_,
            movie0_.actor as actor1_9_0_,
            movie0_.director as director2_9_0_ 
        from
            Movie movie0_ 
        inner join
            Item movie0_1_ 
                on movie0_.ITEM_ID=movie0_1_.ITEM_ID 
        where
            movie0_.ITEM_ID=?
    ```
    <br/>
    :<br/>
    [DTYPE]<br/>
    • DTYPE = 부모 테이블에 값이 입력되었는데, 어떤 자식으로부터 값이 입력된 것인지 알고 싶을 때 사용<br/>
    • [사용방법] 부모 객체에 `@DiscriminatorColumn` 작성, `@DiscriminatorColumn(name=“DTYPE”)` 이름 지정 가능<br/>
    • 추가적으로, 부모테이블에 저장되는 자식테이블에 대한 DTYPE값도 변경할 수 있다.
    • [방법] 자식 객체에 `@DiscriminatorValue(“XXX”)` 이름 지정 가능<br/>
#### 2 )(추천)(단순) 통합 테이블로 변환 = 단일 테이블 전략을 사용(DEFAULT)<br/>
:<br/>
[쿼리문] INSERT 쿼리문이 1회만 만들어지므로 가장 성능이 좋고 find로 찾을 때에도 join의 필요가 없다.
:<br/>
[방법] 상속관계에서 가장 부모인 객체에 `@Inheritance(strategy=InheritanceType.SINGLE_TALBE)` 작성<br/>
:<br/>
[DTYPE]<br/>
• [사용방법] 부모 객체에 `@DiscriminatorColumn`를 생략해도 자동으로 DTYPE칼럼이 생긴다. <br/>
:<br/>
[장점] 조인이 필요 없으므로 일반적으로 조회 성능이 빠름/조회쿼리 단순
[단점] 자식 엔티티가 매핑한 컬럼은 모두 null 허용/단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.<br/>


#### 3 ) (비추천)서브타입 테이블로 변환 = 구현 클래스마다 테이블 전략을 사용 **(사용해서는 안되는 전략)** <br/>
: <br/>
[방법]<br/>
• 상속관계에서 가장 부모인 객체에 `@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)` 작성<br/>
• 부모 클래스를 abstract class 추상 클래스로 작성(객체, 테이블 생성 X)


2. @MappedSuperclass

  • 공통의 매핑정보가 필요할 때 사용

  • 테이블과 매핑되지 않는다.

  • 상속관계 매핑 X

  • 직접 생성할 일이 없으므로, abstract class 추상 클래스로 생성(객체, 테이블 생성 X)

  • 조회, 검색 불가(em.find(BaseEntity) 불가)

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

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

  • @Entity : 상속관계 매핑할 때 사용

    @MappedSuperclass : 공통으로 사용하는 매핑정보 모을 때 사용

package jpabook;

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

@MappedSuperclass
public 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;
    }
}
@Entity
public class Member extends BaseEntity{
...
}

다음과 같이 사용한다.

0개의 댓글