본문 바로가기
Spring/JPA

#7 고급 매핑

by 히포파타마스 2021. 8. 28.

고급 매핑

 

JPA에서 다음과 같은 복잡한 관계를 매핑하기 위한 여러 방법들이 존재한다.

 

● 객체의 상속 관계를 데이터베이스에 맞춰 매핑

● 공통으로 중복되는 값들을 매핑

 

 

 

1. 상속 관계 매핑

관계형 데이터베이스에는 객체지향 언어에서 다루는 상속이라는 개념이 없다.

대신 슈퍼타입 서브타입 관계(Super-Type Sub-Type Relationship)라는 모델링 기법이 객체의 상속 개념과 가장 유사하다.

 

[슈퍼 타입 서브타입 논리 모델]

오른쪽의 객체 간 상속관계와 유사한 슈퍼 타입 서브타입 관계 모델링은 왼쪽과 같이 구성되어있다.

 

슈퍼 타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현할 때는 3가지 방법을 선택할 수 있다.

 

 

 

■ 조인 전략

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

 

[조인 전략 테이블 구조]

 

[조인 전략 매핑]

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
	@Id @GeneratedValue
	@Column(name = "ITEM_ID")
	private Long id;
    
	private String name;
	private int price;
}

@Entity
@DiscriminatorValue("A")
public class Album extends Item {
	private String artist;
}

...

● @Inheritance(strategy = InheritanceType.JOIND)

◎ 상속 매핑은 부모 클래스에 @Inheritance를 사용해야 한다.

◎ 전략에 맞게 strategy를 설정하면 된다(조인 전략이기 때문에 JOIND 사용).

 

● @DiscriminatorColumn(name = "DTYPE")

◎ 테이블에는 타입을 표기할 수 없기 때문에 구분 컬럼을 지정해주어야 한다.

◎ 부모 클래스에 구분 컬럼을 지정한다.

◎ 기본값은 DTYPE이다.

 

● @DiscriminatorValue("A")

◎ 엔티티를 저장할 때 구분 컬럼에 입력할 값을 지정한다.

ex) Album을 저장하면 구분 컬럼인 DTYPE에 A가 저장된다.

 

 

□ 조인 전략의 장단점

● 장점

◎ 테이블이 정규화된다.

◎ 외래 키 참조 무결성 제약조건을 활용할 수 있다.

◎ 저장공간을 효율적으로 사용한다.

 

● 단점

◎ 조회할 때 조인이 많이 사용되므로 성능이 저하될 수 있다.

◎ 조회 쿼리가 복잡하다.

◎ 데이터를 등록할 INSERT SQL을 두 번 실행한다.

 

 

 

■ 단일 테이블 전략

단일 테이블 전략은 이름 그대로 테이블을 하나만 사용한다.

하나의 테이블에 모든 상속 정보를 저장하고 구분 컬럼(DTYPE)으로 어떤 자식 데이터가 저장되었는지 구분한다.

 

[단일 테이블 전략]

 

[단일 테이블 전략 매핑]

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

@Entity
@DiscriminatorValue("A")
public class Album extends Item {
	private String artist;
}

...

@Inheritance의 strategy만 전략에 따라 다르고, 나머지는 앞의 조인 전략과 전부 동일하다.

 

테이블 하나에 모든 것을 통합하므로 구분 컬럼을 필수로 사용해야 한다.

 

 

□ 단일 테이블 장단점

● 장점

◎ 조인이 필요 없으므로 일반적인 조회 성능이 빠르다.

◎ 조회 쿼리가 단순하다.

 

● 단점

◎ 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.

ex) Album을 저장하면 테이블에 Album과 관련된 ARTIST와 Item의 id, name, price를 제외하고 모두 null로 저장된다.

◎ 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.

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

 

 

 

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

이 전략은 자식 엔티티마다 테이블을 만드는 전략이다.

자식 테이블 각각에는 필요한 컬럼이 모두 있다.

 

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

 

이 전략은 여러 자식 테이블을 함께 조회할 때 성능이 느리다(SQL에 UNION을 사용해야 한다).

비슷한 이유로 자식 테이블을 통합해서 쿼리하기 어렵다.

 

이처럼 테이블에서 상속을 매핑하기 위해 발생하는 단점이 명확하기 때문에 일반적으로 권장되지 않는다.

 

 

 

 

2. @MappedSuperclass

부모 클래스는 테이블과 매핑하지 않고 부모 클래스를 상속받는 자식 클래스에게 매핑 정보만 제공하고 싶으면 @MappedSuperclass를 사용하면 된다.

 

[공통 매핑 정보가 필요한 테이블]

Member와 Seller는 서로 관계가 없는 테이블과 엔티티이다.

 

@MappedSuperclass를 사용하면, 테이블은 그대로 두고 객체 모델의 id, name 두 공통 속성을 부모 클래스로 모으고 객체 상속 관계로 만들 수 있다.

 

[@MappedSuperclass 매핑]

@MappedSuperclass
public abstract class BaseEntity {
	@Id @GeneratedValue
	private Long id;
	private String name;
}

@Entity
public class Member extends BaseEntity {
	private String email;
}

@Entity
public class Member extends BaseEntity {
	private String shopName;
}

@MappedSuperclass를 공통 정보를 제공할 부모 클래스에 사용하면 된다.

자식 클래스는 그냥 부모 클래스를 상속 받기만 하면 된다. 

※ @MappedSuperclass는 엔티티가 아니므로 엔티티 매니저나 JPQL등에서 사용할 수 없다.

 

@MappedSuperclass로 지정한 클래스는 직접 생성해서 사용할 일이 거의 없으므로 추상 클래스로 만드는 것이 권장된다.

'Spring > JPA' 카테고리의 다른 글

#9 값 타입  (0) 2021.08.30
#8 프록시와 연관관계 관리  (0) 2021.08.29
#6 다양한 연관관계 매핑  (0) 2021.08.28
#5 연관관계 매핑 기본  (0) 2021.08.27
#4 엔티티 매핑  (0) 2021.08.27

댓글