@TypeDef (Hibernate 5.x)
@TypeDef
는 Hibernate에서 사용자 정의 데이터 타입을 정의할 때 사용하는 어노테이션입니다.
JPA에서는 문자열, 숫자, 날짜 등 기본적인 타입만 매핑할 수 있기 때문에, JSON, Enum과 같은 복잡한 타입을 처리하기 위해서는 Hibernate에서 해당 타입을 어떻게 매핑할 것인지 명시적으로 알려줘야 합니다.
이럴 때 @TypeDef
를 사용하여 사용자 정의 타입을 등록하고, 실제 필드에는 @Type
을 사용하여 적용합니다.
언제 사용하는가?
엔티티 필드가 기본적인 타입이 아닌 경우, Hibernate는 해당 필드를 어떻게 DB에 저장하고 다시 Java 객체로 매핑할지 알 수 없습니다. 이런 경우 @TypeDef
로 사용자 정의 타입을 등록하고, @Type
을 이용하여 해당 필드에 타입 매핑 방식을 지정해줍니다.
import com.vladmihalcea.hibernate.type.json.JsonType;
import com.vladmihalcea.hibernate.type.array.StringArrayType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import javax.persistence.*;
import java.util.Map;
@Entity
@TypeDefs({
@TypeDef(name = "json", typeClass = JsonType.class),
@TypeDef(name = "string-array", typeClass = StringArrayType.class)
})
public class Product {
@Id
private Long id;
@Type(type = "json")
@Column(columnDefinition = "jsonb")
private Map<String, Object> metadata;
@Type(type = "string-array")
@Column(columnDefinition = "text[]")
private String[] tags;
}
@TypeDefs
는 엔티티 안에서 여러 개의 사용자 정의 타입을 등록할 때 사용합니다.@TypeDef
에서 지정한name
값을@Type
어노테이션의type
속성에서 사용합니다.
@Type (Hibernate 6.x / Spring Boot 3.x)
Spring Boot 3.x로 업그레이드되면서 Hibernate 6.x가 적용되었고, @TypeDef
는 더 이상 사용하지 않게 되었습니다.
이제는 각 필드에 직접 @Type
어노테이션을 사용하여 타입 클래스를 지정하는 방식으로 바뀌었습니다.
import com.vladmihalcea.hibernate.type.json.JsonType;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Map;
@Entity
public class UserProfile {
@Id
private Long id;
@Type(JsonType.class)
@Column(columnDefinition = "jsonb")
private Map<String, Object> attributes;
// getter, setter
}
- 클래스 기반으로 타입을 직접 선언하기 때문에 코드가 더 간결하고 가독성이 향상됩니다.
사용 가능한 타입 클래스
@Type
어노테이션에서 사용할 수 있는 클래스는 Hibernate에서 제공하거나 외부 라이브러리에서 제공하는 타입 클래스입니다. 일반적으로 org.hibernate.type.BasicType
또는 org.hibernate.usertype.UserType
인터페이스를 구현하고 있어야 합니다.
1. Json
com.vladmihalcea.hibernate.type.json.JsonType
- 의존성:
hibernate-types-55
또는hibernate-types-60
- 지원 DB: PostgreSQL (jsonb), MySQL (json), Oracle (json 또는 clob)
- Java 타입: Map, List, DTO 등
2. Array
com.vladmihalcea.hibernate.type.array.StringArrayType
com.vladmihalcea.hibernate.type.array.IntArrayType
com.vladmihalcea.hibernate.type.array.LongArrayType
- 지원 DB: PostgreSQL의 배열 타입 (text[], int[] 등)
- Java 타입: String[], int[], long[] 등
3. Enum
com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType
- 지원 DB: PostgreSQL native enum
- Java 타입: Enum
예시 코드
@Type(JsonType.class)
@Column(columnDefinition = "jsonb")
private Map<String, Object> metadata;
@Type(StringArrayType.class)
@Column(columnDefinition = "text[]")
private String[] tags;
@Type(PostgreSQLEnumType.class)
@Column(columnDefinition = "my_enum")
@Enumerated(EnumType.STRING)
private MyStatus status;
DB 종류별 매핑 정리
- PostgreSQL은 JSON, 배열, ENUM, Range 등 다양한 복합 타입을 네이티브로 지원해서 활용도가 높습니다.
- MySQL은 PostgreSQL처럼 json, enum은 지원하지만 배열은 직접 지원하지 않습니다.
- Oracle은 JSON을
CLOB
또는JSON
타입으로 저장할 수 있고, 배열이나 enum에 대한 직접 지원은 부족하지만 우회 가능합니다.
DB | JSON 매핑 | 배열 매핑 | ENUM 매핑 |
---|---|---|---|
PostgreSQL | jsonb + JsonType | text[] + ArrayType | enum + PostgreSQLEnumType |
MySQL | json + JsonType | JSON 배열로 우회 | 기본 enum 처리 가능 (@Enumerated ) |
Oracle | json or clob + JsonType | JSON 배열로 우회 | 기본 enum 처리 가능 (@Enumerated ) |
정리
@TypeDef
는 Hibernate 5에서 사용자 정의 타입을 정의하기 위한 어노테이션입니다.- Spring Boot 3.x부터 Hibernate 6.x가 적용되면서
@TypeDef
없이 필드 단위의@Type(클래스명.class)
방식으로 변경되었습니다. - 마이그레이션 시
@TypeDef
는 제거하고, 각 필드에@Type
어노테이션을 통해 타입 클래스를 직접 지정하면 됩니다. - JSON, 배열, ENUM 등 복잡한 데이터 타입도 Hibernate의 확장 기능을 통해 손쉽게 매핑할 수 있습니다.
반응형
'WEB > Spring JPA' 카테고리의 다른 글
Spring JPA Criteria API 소개와 예제 (0) | 2024.06.07 |
---|---|
Spring Data JPA 어노테이션 OneToMany ManyToOne NamedQuery GeneratedValue (0) | 2024.05.20 |
댓글