JPA 상속관계 매핑
JPA 상속 관계 매핑이란, 객체지향 언어의 상속 개념을 데이터베이스 관계형 모델에 맞게 구현하는 기능이다.
JPA는 객체 모델에서 상속 구조를 데이터베이스에 적절하게 매핑하기 위해 세 가지 전략을 제공한다.
- Joined Table
- Single Table
- Table per Class
JPA에서 상속을 매핑할 때는 상위 클래스에 @Inheritance 어노테이션을 추가해 사용하며, 상속 전략을 지정할 수 있다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Product {
@Id @GeneratedValue
private Long id;
private int price;
}
1. Joined Table 전략
Joined Table 전략은 상위 클래스와 각 하위 클래스마다 별도의 테이블을 생성하고, 하위 클래스 테이블이 상위 클래스 테이블을 참조하도록 설정하는 방식이다. 공통 속성은 상위 클래스 테이블에 저장하고, 하위 클래스마다 필요한 추가 속성은 각자의 테이블에 저장한다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Product { ... }
가장 정규화된 구조로, 다음과 같은 장/단점을 갖는다.
장점
- 필요한 만큼의 데이터베이스 크기를 가진다는 장점이 있다.
단점
- 데이터를 select할때 조인 쿼리가 필요하고 저장시에도 두번의 insert가 발생한다.
2. Single Table 전략
상위 클래스와 모든 하위 클래스를 하나의 통합 테이블로 변환하는 전략이다.
장점
- 모든 데이터가 하나의 테이블에 저장되므로 조회 시 조인이 필요 없다.
단점
- 불필요한 컬럼 : 모든 하위 클래스의 속성이 하나의 테이블에 들어가므로, 특정 하위 클래스에서만 사용하는 컬럼이 많아질 수 있다.
- 저장 공간 낭비 : 위의 이유로 Null 값이 많아지며, 데이터베이스 크기가 커진다.
3. Table per Class 전략
Table per Class 전략은 하위 클래스마다 각각 독립적인 테이블을 생성하는 방식이다. 각 하위 클래스는 테이블은 상위 클래스의 공통 속성과 자신의 속성을 모두 포함하여 개별적으로 저장한다.
장점
- 독립적인 테이블 구조와 하위 클래스 조회 시 조인 불필요
단점
- 데이터 일관성 관리가 어려움 : 공통 속성이 여러 테이블에 중복 저장되면서, 데이터 변경 시 모든 테이블을 일관되게 유지해야 하는 부담이 있다. 공통 속성을 수정하거나 삭제할 때, 모든 하위 클래스 테이블을 개별적으로 수정해야 한다.
- 상위 클래스 타입 조회 시 성능 저하 :
@SpringBootTest
@Transactional
class InheritanceTest {
@PersistenceContext
private EntityManager em;
@Test
void test() {
Book book = new Book(10000, "Harry Potter");
em.persist(book);
em.flush();
em.clear();
Book findBook = (Book) em.find(Product.class, book.getId());
}
}
Book 엔티티를 상위 타입인 Product 타입으로 조회한다고 가정해보자. 로그를 통해 수행되는 쿼리를 보면 아래와 같다.
select
p1_0.id,
p1_0.clazz_,
p1_0.price,
p1_0.title,
p1_0.name
from
(select
price,
id,
title,
null as name,
1 as clazz_
from
book
union
all select
price,
id,
null as title,
name,
2 as clazz_
from
food
) p1_0
where
p1_0.id=?
모든 하위 클래스 테이블에 대해 Union 쿼리가 발생한다.
전략 선택 기준
Joined Table
- 각 하위 클래스가 공통 속성 외에도 다양한 고유 속성을 가지고 있을 경우. 정규화된 구조를 원하거나, 데이터 중복을 피하고자 할 때 적합하다.
Single Table
- 하위 클래스의 종류가 많지 않고, 대다수 공통 속성만 사용할 경우. 조회 성능을 우선시할 때 적합하다.
Table per Class
- 특정 하위 클래스만 조회할 일이 많고, 상위 클래스 타입으로 조회할 일이 거의 없는 경우에 적합하다.
'Programming > Spring,JPA' 카테고리의 다른 글
[JPA/Hibernate] Flush 차이 (0) | 2024.11.22 |
---|---|
[Spring] 예외 처리에만 국한되지 않는 @ControllerAdvice (0) | 2024.10.26 |
[Spring] 단일 행이 반환될때는 queryForObject가 항상 정답일까? (0) | 2024.10.26 |
[Spring] 스프링에서 사용되는 디자인 패턴들 (0) | 2024.10.25 |
[Spring] 스프링 삼각형(IoC/DI, AOP, PSA) (1) | 2024.10.25 |