[JPA] 엔티티 매핑 - @Temporal, @Enumerated, @Lob, @Transient
이전 포스팅에서 기본적인 엔티티 매핑 어노테이션을 알아보았다.
이번 포스팅에서는 다양한 어노테이션을 정리해보겠다.
@Temporal
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Temporal {
TemporalType value();
}
@Temporal은 TemporalType의 컬럼과 매핑되어야 하는 필드를 표시하는 어노테이션이다.
public enum TemporalType {
DATE,
TIME,
TIMESTAMP;
private TemporalType() {
}
}
TemporalType에는 날짜를 나타내는 DATE, 시간을 나타내는 TIME, 날짜와 시간을 나타내는 TIMESTAMP가 있다. 원하는 타입은 @Temporal의 속성에 넣어준다.
@Entity
public class MyEntity {
@Id
private Long id;
@Temporal(TemporalType.DATE)
private Date dateField;
@Temporal(TemporalType.TIME)
private Date timeField;
@Temporal(TemporalType.TIMESTAMP)
private Date timestampField;
}
@Enumerated
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Enumerated {
EnumType value() default EnumType.ORDINAL;
}
@Enumerated는 Enum(열거형) 컬럼과 매핑되어야 하는 필드를 표시하는 어노테이션이다. @Enumerated는 속성으로 EnumType을 설정할 수 있다. 이는 컬럼에 매핑될 때 Enum 타입을 설정하는 것이다.
EnumType에는 두 가지가 있다. STRING, ORDINAL
enum Size {
SMALL, MEDIUM, LARGE
}
STRING은 열거형의 문자열을 의미한다. 레코드 컬럼에 Enum 데이터가 저장될 때, SMALL, MEDIUM, LARGE로 저장된다. ORDINAL은 열거형의 '순서'를 의미한다. SMALL, MEDIUM, LARGE는 0, 1, 2이다. 레코드 커럼에 Enum 데이터가 저장될 때, 0,1,2로 저장된다.
EnumType.ORDINAL은 @Enumerated의 디폴트값이지만 위험하다. 열거형 데이터는 언제든 변경 가능하므로 순서가 매번 바뀔 수 있다. 매번 바뀔때 마다 지정된 번호가 바뀐다면 혼란이 생길 수 있다. 그러므로 @Enumerated 어노테이션을 사용할때는 EnumType.STRING으로 통일하는 것이 안전하고 좋다.
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
@Enumerated(EnumType.STRING)
private Size size;
}
Enum 데이터는 '플래그(flag)' 역할도 한다. 레코드에는 다양한 Product 데이터가 쌓이지만 Enum 컬럼으로 사이즈별로 구분할 수 있다. 회원정보 테이블이라면 회원레코드와 관리자 레코드를 Enum 컬럼으로 구분할 수 있다.
@Lob
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Lob {
}
LOB은 Large Object를 의미한다. 큰 크기의 데이터를 담아야 하는 컬럼은 LOB 형식을 갖는다. LOB 형식은 일반적으로 BLOB(Binary Large Object)와 CLOB(Character Large Object)로 구분되는데, BLOB은 이진 데이터를 저장하는데 사용되며, CLOB은 문자 데이터를 저장하는데 사용된다.
@Lob은 특별한 속성이 없다. @Lob이 표시된 필드나 메소드반환타입에 따라 CLOB이냐 BLOB이냐로 구분된다.
CLOB : String, char[] java.sql.CLOB
BLOV : byte[], java.sql.BLOB
@Entity
public class Product {
@Id
private Long id;
private String name;
@Lob
private String description;
}
상품설명은 많은 내용을 담고 있다. 그래서 대용량 데이터를 담을 수 있는 LOB 타입의 컬럼과 매핑되어야 한다. description의 자료형이 String이니 CLOB과 매핑된다.
@Transient
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transient {
}
일반적으로 어노테이션이 없으면 JPA는 대소문자를 구분하지 않고 필드와 컬럼을 이름을 기준으로 자동 매핑한다. @Transient는 매핑 대상에서 제외할 필드에 표시하는 어노테이션이다. 로직상 임시로 저장할 변수가 필요하여 생성한 것처럼 DB와는 관계없는 변수인 경우 @Transient로 매핑대상에서 제외할 수 있다.
@Entity
public class Order {
@Id
private Long id;
private LocalDate orderDate;
private BigDecimal orderAmount;
@Transient
private OrderStatus orderStatus;
}
주문정보를 저장하려고 한다. 주문ID, 주문날짜, 주문량은 DB 테이블에 매핑되어 저장되지만 주문상태 정보는 저장되지 않는다. 단순히 비즈니스 로직상에 필요한 변수일뿐 DB와는 관계없다.
이렇듯, DB 테이블에는 다양한 형식의 컬럼이 존재하고 JPA는 컬럼형식에 맞는 다양한 어노테이션을 가지고 있다. 원하는 컬럼과 필드를 매핑하고 싶다면 적절한 어노테이션을 선택해야 한다.
참고자료
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard