[JPA] 7. 고급 매핑

DAUN JO·2021년 11월 8일
0

JPA

목록 보기
5/11
post-thumbnail

[JPA] 7. 고급 매핑

자바 ORM 표준 JPA 프로그래밍 공부 기록



📍 상속 관계 매핑

관계형 데이터베이스에는 상속이라는 개념이 없다.
대신에 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 가장 유사하다.


💡 즉 상속 관계 매핑객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑하는 것이다.


  • 슈퍼타입 서브타입 논리 모델을 구현하는 방법
    1. 각각의 테이블로 변환 (= 조인 전략)
    2. 통합 테이블로 변환
    3. 서브타입 테이블로 변환
  • 주요 어노테이션
    @Inheritance(strategy=InheritanceType.~~~)
    • JOINED: 조인 전략
    • SINGLE_TABLE: 단일 테이블 전략
    • TABLE_PER_CLASS: 구현 클래스마다 테이블 전략



1. 조인 전략

엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다.

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {
    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}
  • @Inheritance(strategy = InheritanceType.JOINED)
    상속 매핑은 부모 클래스에 @Inheritance을 사용해야 한다. 여기에 매핑 전략을 설정해야 하는데, 조인 전략을 사용하므로 InheritanceType.JOINED을 사용했다.

  • @DiscriminatorColumn(name="DTYPE")
    부모 클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분할 수 있다. 기본값이 DTYPE이다.



2. 단일 테이블 전략

테이블을 하나만 사용한다. 그리고 구분컬럼(DTYPE)으로 어떤 자식 데이터가 저장되었는지 구분한다. 조인을 사용하지 않으므로 조회 시 제일 빠르다.

주의점은 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다는 것이다. 또한 테이블 하나에 모든 것을 통합하므로 DTYPE을 필수로 사용해야 한다.

  • 장점
    - 조인이 필요 없으므로 조회 성능 굿
    • 조회 커리 단순
  • 단점
    - 단일 테이블이 커질 수 있다. 상황에 따라 성능 오히려 안 좋을 수 있다
  • 특징
    - 구분 컬럼 꼭 사용
    @DiscriminatorColumn 꼭 설정!!!
    • @DiscriminatorColumn을 지정하지 않으면 기본으로 엔티티 이름 사용



3. 구현 테이블마다 테이블 전략

자식 엔티티마다 테이블을 만든다.

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)을 선택하면 구현 클래스마다 테이블 전략을 사용한다. 이는 자식 엔티티마다 테이블을 만든다. 일반적으로는 추천 X

  • 장점
    - 서브 타입을 구분해서 처리할 때 효과적
    • not null 제약조건 사용
  • 단점
    - 여러 자식 테이블 함께 조회할 때 성능 안 좋다
    • 자식 테이블 통합해서 쿼리 어렵다
  • 특징
    - 구분 컬럼 사용 X



📍 @MappedSuperClass

부모 클래스는 테이블과 매핑하지 않고, 부모 클래스를 상속받는 자식 클래스에게 매핑 정보만 제공하고 싶을 때 @MappedSuperClass를 사용

추상 클래스와 비슷한데 @Entity는 실제 테이블과 매핑 되지만 @MappedSuperClass는 실제 테이블과는 매핑되지 않는다.

ex) BaseEntity
객체들이 주로 사용하는 공통 매핑 정보를 정의
테이블과 매핑할 필요가 없고 자식 엔티티에게 공통으로 사용되는 매핑 정보만 제공하면 되므로 @MappedSuperClass를 사용

@MappedSuperclass
public abstract class BaseEntity {

    @Id @GeneratedValue
    private Long id;
    private String name;
    private String createdBy;

}
  • 테이블과 매핑 되지 않고 자식 테이블에 Entity의 매핑 정보를 상속하기 위해 사용
  • Entity가 아니므로 em.find()JPQL에서는 당연히 사용 불가능함
  • 추상 클래스로 만드는 것을 권장
  • @Entity 클래스는 Entity@MappedSuperclass로 지정한 클래스만 상속 가능



상속 관계 매핑 실습


1. 상품의 종류는 음반, 도서, 영화가 있고 이후 더 확장될 수 있다. (상속)

  1. 모든 데이터는 등록일과 수정일이 있어야 한다. (BaseEntity)

Item 테이블

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item {
    @Id
    @GeneratedValue
    @Column(name="ITEM_ID")
    private Long id;

    private String name;
    
    ...
}
  • 상속 관계 매핑하기 위해 Item (부모클래스)에 @Inheritance 사용하고 속성에 InheritanceType.SINGLE_TABLE을 선택해서 단일 테이블 전략 사용

  • 단일 테이블 전략은 구분컬럼을 필수로 사용해야 하므로 @DiscriminatorColumn으로 구분 컬럼 정의하였다.

Book 테이블


@Entity
public class Book extends Item{
    private String author;
    private String isbn;



@MappedSuperclass 매핑


@MappedSuperclass
public abstract class BaseEntity {

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

모든 데이터는 등록일과 수정일을 가져야한다. 이를 모든 엔티티에 하나하나 추가 시키는 것 보다는 @MapperSuperclass를 사용하여 각 클래스에 상속시키는 것이 효율적이다.

profile
🍕

0개의 댓글