[JPA] 고급 매핑

gyeol·2024년 7월 15일

JPA

목록 보기
6/13
post-thumbnail

김영한 님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'를 듣고 적은 글 입니다.

상속 관계 매핑

객체는 상속 관계가 존재하지면 관계형 데이터베이스는 상속 관계가 존재하지 않는다.
이때 슈퍼타입, 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.

슈퍼타입 서브타입 논리 모델 -> 물리 모델

  • 조인 전략 : @Inheritance(strategy = InheritanceType.JOINED) 사용
  • 단일 테이블 전략 : @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
  • 구현 클래스마다 테이블 전략 : @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
  • @DiscriminatorColumn(name = "DTYPE") 사용 시 자식 객체 타입 알 수 있음

조인 전략

각 테이블에서 데이터를 조회할 때 조인을 사용해 조회하는 전략이다.

각각의 클래스를 만들고 부모 클래스에

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

이렇게 적어주면 조인 전략으로 데이터베이스가 설계되며 이때 @DiscriminatiorColumn 애노테이션 덕분에 DTYPE이라는 칼럼도 생겨 어떤 타입인지도 조회할 수 있게 된다.


이렇게 자식 객체가 Movie임을 확인할 수 있다.

하지만 이때 INSERT 쿼리가 두번이나 나가는 것을 확인할 수 있다.

장점

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

단점

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

단일 테이블 전략

조인 전략처럼 테이블을 세분화해서 설계하지 않고 한 테이블에 모든걸 다 때려박는다.
이렇게 되면 조회 성능도 빨라지고 조회 쿼리가 단순해진다.

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

위와 똑같은 클래스에서 전략만 SINGLE_TABLE로 바꿔준 뒤 실행하면

이와 같이 모든 컬럼들이 한 테이블에 들어간 것을 확인할 수 있다.
이때 굳이 @DiscriminatorColumn 애노테이션을 사용하지 않아도 DTYPE은 생성된다.


조인 전략에선 INSERT 쿼리가 두번 나갔지만 단일테이블 전략에서는 INSERT 쿼리가 한 번만 실행되는 것도 확인할 수 있었다.

장점

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

단점

  • 자식 엔티티가 매핑한 컬럼은 모두 null 사용
  • 단일 테이블에 모든 것을 저장하기에 테이블이 커지고, 이에 따라 조회 성능이 저하될 수 있음

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

조인 전략과 비슷하지만 ITEM 테이블을 없애고 부모 클래스가 가진 속성을 다 밑으로 내린 것이다.

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

TABLE_PER_CLASS 전략으로 바꿔주면 ITEM 테이블은 생성되지 않고 각각의 하위 테이블들만 생성된다.

장점

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

단점

  • 여러 자식 테이블을 함께 조회할 때 성능 느림(UNION SQL 필요)
  • 자식 테이블을 통합해 쿼리하기 어려움

추천하지 않는 전략이다..!

@MappedSuperclass

공통 매핑 정보가 필요할때 사용한다.
테이블과 관계 없고 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할을 한다.
예를 들어, Member 클래스와 Seller 클래스에서 공통된 속성인 id와 name을 가지고 있다면

이와 같은 구조로 나타낼 수 있다.
물론 데이터베이스에선 MEMBER테이블과 SELLER테이블에서 id와 name을 갖도록 한다.

@MappedSuperclass
public class BaseEntity {
.
.
.
}

이와 같이 BaseEntity 클래스를 만들고 각각 MemberSeller 에서 BaseEntity 클래스를 상속받도록 한다.

그럼 이와 같이 내가 BaseEntity에서 만든 속성들을 MEMBER 테이블에서 가지고 있는 것을 확인할 수 있다.

@MappedSuperclass는 상속관계 매핑이 아닌, 부모 클래스를 상속 받는 자식 클래스에 매핑정보만 제공한다. 이때 BaseEntity 클래스는 조회, 검색할 수 없다.
직접 생성해 사용할 일이 없기에 추상클래스로 만드는 것을 권장한다.

profile
공부 기록 공간 '◡'

0개의 댓글