DevKim

[JPA] 상속관계 매핑 & MappedSuperclass 본문

JPA

[JPA] 상속관계 매핑 & MappedSuperclass

on_doing 2021. 6. 21. 21:32
728x90

관계형 DB는 상속관계가 없지만, 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하기 때문에

이것을 이용하여 객체의 상속과 구조와 관계를 매핑할 수 있다.


[ JOINED 전략 ]

@Getter @Setter
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item {

    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;

    private String name;
    private int price;
}

조인 전략을 사용하기 위해 Inheritance를 설정해주었고,

Movie만 임의로 저장해서 확인하니 알맞게 저장된 것을 확인할 수 있다.

@DiscriminatorColumn으로 DTYPE 넣어줌으로써 뭐 때문에 Item 테이블에 들어온건지를 알 수 있다.

(꼭 넣어주는게 운영상 좋다고한다)

 

만약 회사에서 DBA분이 회사 규칙상 Movie는 M으로 저장해야한다고 하면, @DiscriminatorValue("M")을 Movie클래스에 추가해주어야한다. 

Movie movie =new Movie();
            movie.setDirector("영화감독");
            movie.setActor("공유");
            movie.setName("공유의영화");
            movie.setPrice(100000);

            em.persist(movie);

쿼리 로그를 보기위해,

flush로 db에 저장해주고 1차캐시 모두 지워준뒤 조회하니 inner join이 일어나면서

영화정보를 잘 가져온 것을 확인할 수 있었다.

/*
조회
*/

em.flush();
em.clear();

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

tx.commit();

inner join을 Item으로해서 movie가져옴

 

장점은 테이블 정규화에 따른 저장공간이 효율적이고 설계가 깔끔하다.

단점은 조회시 조인을 많이 사용하다보니 성능이 저하될 수 있고(조금..) 조회시 단일 테이블보단 복잡하다.


[ SINGLE_TABLE 전략 ]

단일 테이블은 @DiscriminatorColumn 없이도 DTYPE이 자동으로 생성된다.

 

[Item]

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Item {

    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;

    private String name;
    private int price;
}

 

[Book]

@Entity
@DiscriminatorValue("B") //DB에 저장될 때 Book은 B로 구분됨
public class Book extends Item {

    private String author;
    private String isbn;
}

 

단일 테이블 전략은 장점으론 테이블이 하나이기에 조회 쿼리가 단순하고, 일반적으로 조회 성능이 빠르다.

단점으론, 자식 엔티티가 매핑한 컬럼은 모두 아래와 같이 null을 허용해야하고,

상황에 따라 조회 성능이 오히려 느려질 수 있다.


[ TABLE_PER_CLASS 전략]

구현 클래스마다 각각의 정보를 가지고 있는 전략으로, 단점이 너무 치명적이기때문에 고려할 필요도 없다고한다.

 

 

조인 전략을 기본 전략으로 가져가는게 좋고, 정말 단순하고 데이터도 별로 안되면 단일 테이블 전략으로 가져가면된다.

trade off가 있기 때문에 상황에 따라 둘 사이에서 고민하는 것이 좋다고한다.

 


@MappedSuperclass

만약 누가 테이블을 수정했고, 언제 수정했고, 누가 등록했고..같이 전체 엔티티에서 공통으로 사용하는 정보를 추가해야할 때 모든 곳에 추가하기 번거로우니 BaseEntity를 만들어서 상속 받는 자식 클래스에 매핑 정보만 제공하는 것이다.

단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할을 한다.

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

 사용하고 싶은 엔티티에서 extends로 상속 받아서 사용하면 된다.

 

*  상속관계매핑도 아니고 엔티티도 아니기에 테이블과 매핑되지도 않는다. (테이블과 관계없음)

* 직접 생성해서 사용할 일이 없으므로 추상 클래스로 생성하는 것이 좋다.

 

참고 강의, 자료 출처

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 본 강의는 자바 백엔

www.inflearn.com

 

728x90
Comments