@NoArgsConstructor
)가 필수이다.@Temporal
은
해당 필드가 날짜(DATE), 시간(TIME),타임스탬프(TIMESTAMP) 중에
어떤 유형으로 저장되어야 하는지를 명시하기 위해 사용되는 어노테이션이다.
java.util.Date
, java.util.Calendar
TemporalType.DATE
: 날짜 (yyyy-MM-dd)TemporalType.TIME
: 시간 (HH:mm:ss)TemporalType.TIMESTAMP
: 날짜 + 시간 (yyyy-MM-dd HH:mm:ss)@Column(updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
TIMESTAMP
는 지원되는 미래 연도가 짧으므로DATETIME
으로 설정하는 것이 좋다.java.time
패키지의 클래스이며, Java 8에서 도입된
날짜와 시간을 함께 표현할 수 있는 불변 객체이다.
Java 8 이상을 사용하는 경우, java.time
패키지를 사용하는 것이 권장된다.
JPA 2.2 및 Hibernate 5 이상에서는 @Temporal
어노테이션을 사용하지 않아도
MYSQL의 경우, 자동으로 TIMESTAMP
or DATETIME
으로 매핑된다.
@Column(updatable = false)
private LocalDateTime createdAt;
JPA에서 엔티티 생성/수정 시점을 자동으로 입력해주는 어노테이션이다.
java.util.Date
나 Calendar
를 사용할 경우에는 @Temporal
어노테이션이 필수이다.
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
@EnableJpaAuditing
config
패키지@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Entity
@Table(name = "users")
@Getter
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true) // ✅ 유니크 제약
private String email;
@Column(nullable = false)
private String password;
@Column(nullable = false, unique = true)
private String nickname; // ✅ 유니크 제약
....
위와 같은 User
엔티티가 있다고 가정하자.
키 값이 이미지처럼 랜덤으로 설정되면 디버깅 및 예외처리에 식별하기 어려워진다.
Duplicate entry 'example@example.com' for key 'UK_8f8e4f3b8a2b3e9a'
유니크 키 제약조건 위반시 뜨는 에러 문구이다.
위와 같이 식별하기 어렵기 때문에 어떤 필드인지 파악하기 어려워진다.
따라서 @Table의 uniqueConstraints를 사용하는 것을 더 추천한다.
보통 IDENTITY 전략을 많이 쓰게 된다.
IDENTITY
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
SEQUENCE
TABLE
JPA와 영속성 컨텍스트
JPA는 보통 객체를 영속성 컨텍스트에 등록한 후,
트랜잭션을 커밋하거나 flush()
를 호출하는 시점에 INSERT 쿼리를 실행한다.
하지만 IDENTITY 전략을 사용할 경우, 예외가 발생한다.
객체를 생성할 때, Id
값이 null이기 때문에
객체가 영속성 컨텍스트에 들어가기 전에, ID 값을 알아야 한다.
따라서 JPA는 IDENTITY 전략을 사용하는 엔티티를 persist()하는 즉시
DB에 INSERT 쿼리를 날려 ID 값을 받아서 1차캐시에 저장한다.
new → persist() → 영속 상태(INSERT 미실행) → flush() or commit() → INSERT 실행
new → persist() → INSERT 실행 (즉시 ✅) → 생성된 ID 값을 받아와 1차 캐시(영속성 컨텍스트)에 저장
w3schools-java_date
unique 속성을 지양해야 하는 이유
김영한 자바 ORM 표준 JPA 프로그래밍