[JPA] 고급 매핑

윤경·2021년 10월 17일
1

JPA

목록 보기
9/22
post-thumbnail

[1] 상속관계 매핑

실습은 ex1-hello-jpa로 진행되었습니다.
DB: .../~/test

상속관계 매핑

  • 관계형 데이터베이스는 상속 관계가 없다.
  • 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
  • 상속관계 매핑: 객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑

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

  • 각각 테이블로 변환 → JOINED
  • 통합 테이블로 변환 → SINGLE_TABLE
  • 서브타입 테이블로 변환 → TABLE_PER_CLASS (구현 클래스마다 테이블)

➡️ @Inheritance(strategy=InheritanceType.XXX)
XXX 자리에 JOINED, SINGLE_TABLE, TABLE_PER_CLASS 중 하나를 넣으면 된다.

또 다른 주요 어노테이션

  • @DiscriminatorColumn(name="DTYPE")
  • @DiscriminatorValue("XXX")

JOIN 전략

// JpaMain.java
        try {
            Movie movie = new Movie();
            movie.setDirector("A");
            movie.setActor("B");
            movie.setName("불한당");
            movie.setPrice(10000);

            em.persist(movie);

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

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

            tx.commit();
        } catch (Exception e) {

db쿼리

장점

  • 테이블이 정규화 되어있음
  • 외래 키 참조 무결성 제약조건 활용 가능
  • 저장공간 효율화

단점

  • 조회시 조인을 많이 사용, 성능 저하
  • 조회 쿼리가 복잡
  • 데이터 저장시 INSERT SQL 2번 호출

SINGLE_TABLE 전략

: 논리 모델을 한 테이블로 합쳐버림

📌 Item.java@Inheritance(strategy = InheritanceType.JOIN) ➡️ @Inheritance(strategy = InheritanceType.SINGLE_TABLE)로 변경하기만 하면 됨

tabledb

장점

  • 조인이 필요 없어 일반적으로 조회 성능이 빠름
  • 조회 쿼리 단순

단점

  • 자식 엔티티가 매핑한 컬럼은 모두 null 허용(치명적 단점)
  • 단일 테이블에 모든걸 저장해 테이블이 커질 수 있음. 상황에 따라 또 조회 성능이 느려질 수 있음.

TABLE_PER_CLASS

📌 Item.java@Inheritance(strategy = InheritanceType.XXX) ➡️ @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)로 변경하기만 하면 됨

db

장점

  • 서브 타입을 명확히 구분해 처리할 때 효과적
  • not null 제약 조건 사용 가능

단점

  • 여러 자식 테이블을 함께 조회할 때 성능이 느림(UNION SQL 필요)
    (→ 말하자면 뭘 찾을 때 다 찔러봐야 하니까 비효율적)
  • 자식 테이블을 통합해 쿼리하기 어려움

TABLE_PER_CLASS 전략은 DB 설계자와 ORM 전문가 그 누구에게도 추천하지 않는다^^,,


[2] Mapped Superclass - 매핑 정보 상속

@MappedSuperclass

: 아래와 같이 공통 매핑 정보가 필요할 때 사용

// BaseEntity.java
package hellojpa;

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

@MappedSuperclass   // 매핑 정보만 받는 부모 클래스
public class BaseEntity {
    private String createBy;
    private LocalDateTime createDate;
    private String lastModified;
    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 getLastModified() {
        return lastModified;
    }

    public void setLastModified(String lastModified) {
        this.lastModified = lastModified;
    }

    public LocalDateTime getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(LocalDateTime lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}
// Member.java
public class Member extends BaseEntity {

// Team.java
public class Team extends BaseEntity {

// JpaMain.java
    try {
            Member member = new Member();
            member.setUsername("userA");
            member.setCreateBy("Yoon");
            member.setCreateDate(LocalDateTime.now());

            em.persist(member);

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

            tx.commit();
        } catch (Exception e) {

실행결과 마찬가지로 Team에도 생성됨

  • 상속관계 매핑이 아님 (헷갈리지 않도록 조심)
  • 엔티티가 아니며 테이블과 매핑이 안됨
  • 부모 클래스를 상속 받는 자식 클래스에 !!매핑 정보만!! 제공
  • 조회, 검색 불가(em.find(BaseEntity) 불가능)
  • 직접 생성해 사용할 일이 없으므로 추상 클래스 권장
  • 테이블과 관계가 없으며 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할
  • 주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용

📌 @Entity(상속 관계 매핑할 때 사용) 클래스는 엔티티나 @MappedSuperclass(속성만 상속할 때 사용)로 지정한 클래스만 상속 가능


[3] 실전 예제 - 4. 상속관계 매핑

해당 실습은 jpabook/jpashop으로 진행하였습니다.
DB: /~/jpashop

👩🏻‍💻 추가 요구사항

  • (상속 관계 매핑) 상품의 종류는 음반, 도서, 영화. 그리고 이후 확장 가능.
  • (MappedSuperclass) 모든 데이터는 등록일, 수정일을 가짐.

도메인 모델

상세테이블설계

싱글 테이블 전략

// Item.java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item extends BaseEntity {

싱글테이블 db

조인 전략

// Item.java
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item extends BaseEntity {

조인 db 하지만 우린 싱글테이블 속성을 사용할 것

BaseEntity 적용


profile
개발 바보 이사 중

0개의 댓글