jae_coding

[Spring JPA] 상속관계 매핑 (Superclass) 본문

Spring, java/Spring_JPA

[Spring JPA] 상속관계 매핑 (Superclass)

재코딩 2022. 9. 13. 20:08
반응형

목차

  • 상속관계 매핑
  • Superclass

 

1. 상속관계 매핑

RDBMS는 상속관계가 존재하지 않는다.

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

 

예제

 

슈퍼타입, 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법?

  • 각각의 테이블로 변환 👉 조인 전략

테이블 데이터를 각각 만들어 둔 상태에서 부모 테이블과 자식 테이블을 둘다 insert한 후 join하는 전략이다.

부모 테이블은 구분하는 Column을 둔다. 예를 들어 ITEM의 DTYPE이다.

 

예제를 똑같이 따라하는 방식으로 진행해 보았다.

 

ALBUM

package hellojpa;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("ALBUM")
public class Album extends Item{
    private String artist;
}

 

BOOK

package hellojpa;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("BOOK") // default: class명
public class Book extends Item{
    private String author;

    private String isbn;

}

MOVIE

package hellojpa;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("MOVIE")
public class Movie extends Item{
    private String director;

    private String actor;

    public String getDirector() {
        return director;
    }

    public void setDirector(String director) {
        this.director = director;
    }

    public String getActor() {
        return actor;
    }

    public void setActor(String actor) {
        this.actor = actor;
    }
}

 

ITEM

package hellojpa;

import javax.persistence.*;

@Entity
// Join 전략
@Inheritance(strategy = InheritanceType.JOINED)
// INSERT DTYPE
@DiscriminatorColumn
public class Item {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private int price;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

MAIN

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;


public class jpaMain {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
            Movie movie = new Movie();
            movie.setDirector("A");
            movie.setActor("B");
            movie.setName("바람과 함께 사라지다");
            movie.setPrice(10000);
            em.persist(movie);

            //1차 캐시 초기화
            em.flush();
            em.clear();

            System.out.println("=============");
            Movie findMovie = em.find(Movie.class, movie.getId());
            System.out.println("findMovie = " + findMovie);
            System.out.println("=============");

            tx.commit();
        } catch (Exception e){
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();
    }
}

DB확인

 

조인 전락

- 장점: 테이블 정규화, 외래 키 참조 무결성 제약조건 활용가능, 저장공간 효율화

- 단점: 조회시 조인을 많이 사용하기에 성능 저하, 조회 쿼리가 복잡함, 데이터 조회시 INSERT SQL 2번 호출

 

 

  • 통합 테이블로 변환 👉 단일 테이블 전략

단일 테이블 전략은

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

로 변경해주어야 한다. (JOIN -> SINGLE_TABLE)

데이터를 한 테이블에 모두 넣는 방식이다.

 

싱글 테이블 전략

- 장점: 조인이 필요없기때문에 일반적으로 조회 성능이 빠름, 쿼리가 단순함

- 단점: 자식 엔티티가 매핑한 컬럼은 모두 null, 단일 테이블에 모든 것을 저장하기때문에 테이블이 커질 수 있다. 상황에 따라 조회 성능이 떨어질 수 있다.

 

 

  • 서브타입 테이블로 변환 👉 구현 클래스마다 테이블 전략 (설계자와 ORM 전문가 둘다 추천하지 않음)

자녀 클레스를 각각의 테이블로 만드는 방식이다.

 

 

2. Superclass (@MappedSuperclass)

 

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

 

객체 입장에서 id와 name같은 column이 공통일때, 속성만 상속해서 사용하고 싶을 경우에 사용한다.

DB는 완전히 다르지만 객체입장에서는 공통속성을 공유하고 싶을 경우에 사용된다.

 

- 상속관계 매핑 x

- 엔티티, 테이블과 매핑 x

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

- 조회, 검색 불가

- 직접 생성해서 사용할 일이 없다 👉 추상 클레스로 사용

 

BaseEntity 생성

package hellojpa;

import java.time.LocalDateTime;

public class BaseEntity {

    private String createBy;
    private LocalDateTime createDate;
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;

    public String getCreateBy() {
        return createBy;
    }

    public void setCreateBy(String createBy) {
        this.createBy = createBy;
    }

    public LocalDateTime getCreateDate() {
        return createDate;
    }

    public void setCreateDate(LocalDateTime createDate) {
        this.createDate = createDate;
    }

    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
public class Member extends BaseEntity{
@MappedSuperclass
public class Team extends BaseEntity{

 

위와 같은 방식으로 공통 속성을 공유할 수 있다.

 

반응형
Comments