| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- NamedEntityGraph
- 오블완
- +9:00
- MSSQL
- createEntityGraph
- 운동해서 광명찾자
- spring boot
- mysql8업그레이드
- getEntityGraph
- MYSQL
- yml
- RootGraph
- jdbc characterencoding utf8mb4
- 운영체제별 차이
- mysql =
- mysql equal null
- load order
- Protecle
- java jdbc utf8mb4 연결 오류
- 1*1000
- jdbc utf8mb4
- getDateCellValue
- sendFractionalSeconds
- https
- AuditingEntityListener
- 티스토리챌린지
- fractional seconds
- apatch poi
- 버전 문자열 비교
- mysql not equal null
- Today
- Total
Hello
[jpa+hibernate] 두 개의 Enum으로 JPA상속 Hibernate @DiscriminatorFormula 활용 본문
[jpa+hibernate] 두 개의 Enum으로 JPA상속 Hibernate @DiscriminatorFormula 활용
nari0_0 2025. 11. 7. 14:20데이터베이스에 두 개의 Enum 컬럼이 존재하고 어플리케이션에서는 Enum 값을 조합하여 클래스 단위로 구분해 처리한 내용을 JPA 상속 매핑 전략, Hibernate의 @DiscriminatorFormula 활용, 조합형 Enum을 엔티티에서 사용 방법으로 나눠 정리하고자 합니다.
1. JPA 상속 매핑 전략
JPA는 상속 구조를 테이블에 매핑하기 위해 세 가지 전략을 제공함.
| 전략 | 특징 |
| SINGLE_TABLE | 모든 상속 엔티티를 하나의 테이블에 저장함 |
| JOINED | 부모/자식 테이블 분리 후 조인함 |
| TABLE_PER_CLASS | 자식별 독립 테이블 사용함 |
- @DiscriminatorColumn과 @DiscriminatorValue
구분컬럼(discriminator column)을 통해 어떤 엔티티 타입인지 판별
ex) 아래 예시 코드에서 dtype은 JPA가 직접 관리하는 컬럼이다.
new Movie()를 저장하면 JPA가 dtype='MOVIE'로 값을 자동으로 넣어준다.(쓰기, 읽기 모두 JPA가 처리해준다.)
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype")
public abstract class Item {
@Id @GeneratedValue
private Long id;
}
@Entity
@DiscriminatorValue("MOVIE")
public class Movie extends Item {
private String director;
}
2. Hibernate 확장 : @DiscriminatorFormula
한 컬럼으로 타입을 구분하기 어려울 때 사용합니다.
ex) 가격, 장르 조합으로 엔티티 구분이 필요한 경우 이 때! Hibernate가 만든 확장 기능인 @DiscriminatorFormula를 사용하면 쉽게 처리 가능합니다.
public enum Genre {
ACTION, COMEDY;//장르
}
public enum PriceLevel {
LOW, HIGH;//가격 수준
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula("concat(genre, '_', price_level)")
public abstract class Item {
@Id
@GeneratedValue
private Long id;
@Enumerated(EnumType.STRING)
@Column(name = "genre")
private Genre genre;
@Enumerated(EnumType.STRING)
@Column(name = "price_level")
private PriceLevel priceLevel;
private String title;
// getters, setters
}
@Entity
@DiscriminatorValue("ACTION_LOW")
public class ActionLowMovie extends Item {
private String director;
// getters, setters
}
@Entity
@DiscriminatorValue("COMEDY_HIGH")
public class ComedyHighMovie extends Item {
private String actor;
// getters, setters
}
Hibernate 내부쿼리
select id, genre, price_level, concat(genre, '_', price_level) as clazz_ from item;
clazz_ = "ACTION_LOW" -> ActionLowMovie 매핑됩니다.
@DiscriminatorFormula는 읽기 전용 식이므로, JPA가 직접 값을 저장하지 않습니다. genre, price_level 컬럼을 개발자가 직접 세팅해야 합니다.
| 구분 | 역할 |
| @DiscriminatorColumn | 읽기 쓰기 |
| @DiscriminatorFormula | 읽기 |
3. 문자열 구분 규칙과 @DiscriminatorValue
Formula와 동일한 규직으로 작성해야 하며 구분자( _ )는 자유롭가 사용 가능합니다.
4. 조합형 Enum활용
두 개 이상의 Enum을 조합해 어플리케이션에서 의미있는 하나의 타입으로 사용할 수 있습니다.
DB에는 genre, price_level 컬럼이 저장되고 엔티티를 조회할 때 자동으로 combinedType이 세팅 됩니다.
@Entity
public class Item {
...
@Transient
public CombinedMovieType computeCombined() {
this.combined = CombinedType.of(genre, priceLevel);
}
}
public enum CombinedMovieType {
ACTION_LOW(Genre.ACTION, PriceLevel.LOW),
ACTION_HIGH(Genre.ACTION, PriceLevel.HIGH),
COMEDY_LOW(Genre.COMEDY, PriceLevel.LOW),
COMEDY_HIGH(Genre.COMEDY, PriceLevel.HIGH);
private final Genre genre;
private final PriceLevel priceLevel;
CombinedMovieType(Genre genre, PriceLevel priceLevel) {
this.genre = genre;
this.priceLevel = priceLevel;
}
public static CombinedMovieType of(Genre g, PriceLevel p) {
for (CombinedMovieType type : values()) {
if (type.genre == g && type.priceLevel == p) {
return type;
}
}
throw new IllegalArgumentException("No matching CombinedMovieType");
}
}
정리
| 상황 | 권장 사용 |
| 단일 컬럼으로 구분 가능 | @DiscriminatorColumn |
| 여러 컬럼 조합으로 구분 | @DiscriminatorFormula |
| Enum조합 표현 | @Transient |
JPA 표준은 단일 구분 컬럼(@DiscriminatorColumn)만 지원
Hibernate는 이를 확장 해 여러 컬럼을 조합한 식(@DiscriminatorFormula)으로 타입 구분을 지원합니다.(읽기)
단순 구분 조합은 상속 하지 않고 두 Enum을 갖는 새로운 Enum을 만들어 @Transient로 처리할 수 있습니다.
'java' 카테고리의 다른 글
| MySQL dependency 8.0.18 에서 8.2.0으로 업그레이드 시 만난 datetime 이슈 (0) | 2025.04.15 |
|---|---|
| MySQL 5에서 8로 업그레이드 시 utf8mb4와 JDBC characterEncoding 옵션 설정 (0) | 2025.04.01 |
| [Stream] 그룹핑 후 정렬 처리 (0) | 2025.02.07 |
| [Hibernate] Inheritance Mapping (0) | 2024.11.07 |
| [Querydsl] Subquery 및 Result handling (0) | 2024.07.31 |