[김영한 - JPA 기본] #7 고급매핑

핵심 요약


  • JOINED : 조인전략

    • 사실상 이게 메인
    • 중요한 도메인에 해당 !
@Inheritance(strategy = InheritanceType.JOINED)
  • SINGLE_TABLE : 단일

    • 가볍게 가져갈때
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
  • TABLE_PER_CLASS : 구현 클래스마다 테이블 전략
    • worst
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

상속 관계 매핑


  • 기본적으로 관계형 DB는 상속관계가 없다
    그러나 슈퍼타입, 서브타입 모델링 기법은 객체 상속과 유사하다

  • 객체의 상속구조와 DB의 슈퍼, 서브타입 관계를 매핑한다

주요 어노테이션


// 상속 관계 전략 설정
@Inheritance(strategy=InheritanceType.XXX)
 JOINED : 조인 전략
 SINGLE_TABLE : 단일 테이블 전략
 TABLE_PER_CLASS : 구현 클래스마다 테이블 전략

// JOINED, SINGLE_TABLE 선택시 구분자 컬럼명
@DiscriminatorColumn(name=DTYPE)

// 컬럼의 값 명, default는 Entity 명이다
// 예) Album 엔티티는 Album 으로 값이 설정됨
@DiscriminatorValue(XXX)

실제 매핑 예시


@Entity
@DiscriminatorValue("A") // 이런 약어는 지양하는게 좋다
public class Album extends Item {

	private String artist;

  ...

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "D_COL")
abstract public class Item {

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

  ...

조인전략


@Inheritance(strategy = InheritanceType.JOINED)
  • 장점

    • 테이블들이 자연스럽게 정규화됨
    • 외래키 참조 무결성 제약조건 활용 가능
      • ID로 서로 연결하여 값을 가져올 수 있다
    • 상속관계를 이용함으로써 저장공간 효율화
  • 단점

    • 조회시 조인을 많이 사용, 성능 저하
      • 그러나 인덱스 등을 이용해서 최적화 가능 !

    • 조회 쿼리가 복잡함
      • 우리가 쿼리를 작성하지 않아 !!

    • 데이터 저장시 INSERT 쿼리 2번 호출

단일 테이블 전략


@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
  • 장점

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

    • 자식 엔티티가 매핑한 컬럼은 모두 null 허용
      • 예를들어 Album 객체를 테이블에 넣을시 Movie, Book 등의 컬럼 정보는 당연히 null 이다

    • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서 조회 성능이 오히려 느려질 수 있다

구현 클래스마다 테이블 전략


@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
  • 이 전략은 DB 설계자와 ORM 전문가 모두 다 추천하지 않는다

  • 장점
    • 서브 타입을 명확하게 구분해서 처리할 때 효과적
    • not null 제약 조건 사용가능
  • 단점
    • 여러 자식 테이블을 함꼐 조회할 때 성능이 느림 (UNION SQL 필요)
      • 예시에 있는 Item의 Price 를 보고 싶을 떄 , 즉 가격을 정산할 떄 모든 테이블을 긁어 모은다

    • 자식 테이블을 통합해서 쿼리하기 어려움

@MappedSuperclass


  • 공통 매핑 정보가 필요할 때 사용한다
    • 엔티티가 공통으로 사용하는 매핑 정보를 모음
  • 상속관계 매핑과는 완전히 다른 개념이다 !
  • 엔티티가 아니며 따라서 테이블과 매핑되는 개념도 아니다
    • 테이블이 별도로 생성되는 개념이 아니다
      따라서 당연히 조회, 검색이 불가하다

      em.find(BaseEntity) 불가

  • 부모 클래스를 상속 받는 자식에 매핑 정보만을 제공한다
  • 직접 생성해서 사용하는 개념이 아니므로 추상 클래스 abstract를 사용하자 !

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

  • 참고: @Entity 클래스는 엔티티나 @MappedSuperclass로 지정한 클래스만 상속 가능하다

현재날짜, 현재 사용자의 세션 등의 정보를 어노테이션으로 자동으로 넣는 것도 가능하다 (이후 강의)

예제 코드


@Entity
public class Member extends BaseEntity {
  ...
}
@MappedSuperclass
public class BaseEntity {

	@Column(name = "CREATED_BY")
	private String createdBy;

	@Column(name = "CREATED_AT")
	private LocalDateTime createdAt;

	@Column(name = "LAST_MODIFIED_BY")
	private String lastModifiedBy;

	@Column(name = "LAST_MODIFIED_AT")
	private LocalDateTime lastModifiedAt;
}




© 2020.12. by 따라쟁이

Powered by philz