2월 25, 2024

[JPA] @CreatedDate, @CreatedBy, @LastModifiedDate, @LastModifiedBy, auditorAware, @EnableJpaAuditing 통해서 생성일시, 변경일시 관리하기

1. Intro

데이터를 관리할 때 처음 저장된 일시, 유저, 마지막으로 저장된 일시, 유저 데이터를 관리하는 것은 중요하다. 오늘은 JPA에서 annotation을 사용해서 이들을 관리하는 방법을 알아보도록 하겠다. 

2. Annotation

1) @CreatedDate

데이터가 "생성된 시간 정보"를 관리하는 annotation이다. 참고로 main method가 실행되는 class에 @EnableJpaAuditing annotation을 적용하여야 이 일시에 null이 아닌, 실제 생성된 시간 정보가 들어간다. 

3. @CreatedBy

처음 데이터를 생성한 user 정보를 넣어준다. @CreatedDate와는 달리 따로 Spring에서 알 수 있는 방법이 없기 때문에 따로 auditorAware를 사용하여 구현해줄 수 있다.

package com.example.projectboard.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import java.util.Optional;

@EnableJpaAuditing
@Configuration
public class JpaConfig {

@Bean
public AuditorAware<String> auditorAware(){
return () -> Optional.of("user1");
}
}

3) @LastModifiedDate

2번 @CreatedDate와 비슷하게 일시를 나타내주는 데이터인데, @LastModifiedDate를 통해 가장 마지막으로 변경된 일시를 나타내준다. 

change된 데이터의 이력을 관리하는 목적으로 사용된다.

4) @LastModifiedBy

3번 @CreatedBy와 유사하게 데이터를 변경한 사용자를 관리하는 목적으로 사용된다. @CreatedBy가 가장 처음에 데이터를 생성한 유저를 나타낸다면 @LastModifiedBy는 가장 마지막으로 데이터를 변경한 유저를 나타낸다. 

3. 예시코드 - 생성일시, 변경일시 등을 관리하는 게시글 Entity 만들기

위 네 개의 데이터를 관리할 수 있는 것이 대표적으로 게시글이라고 할 수 있다. Article이라는 이름으로 Entity를 만들면 아래와 같이 만들 수 있다. 전체 코드를 아래와 같이 살펴보자. 

package com.example.projectboard.domain;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.LocalDateTime;
import java.util.Objects;

@Getter
@ToString
@Table(indexes = {
@Index(columnList = "title"),
@Index(columnList = "createdAt"),
@Index(columnList = "createdBy")
})
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Setter
private String title;
@Setter @Column(nullable = false) private String content;

@CreatedDate @Column(nullable = false) private LocalDateTime createdAt;
@CreatedBy @Column(nullable = false, length = 200) private String createdBy;
@LastModifiedDate @Column(nullable = false) private LocalDateTime modifiedAt;
@LastModifiedBy @Column(nullable = false, length = 200) private String modifiedBy;

protected Article(){

}

private Article(String title, String content) {
this.title = title;
this.content = content;
}

private Article of(String title, String content) {
return new Article(title, content);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Article article)) return false;
return id != null && id.equals(article.id);
}

@Override
public int hashCode() {
return Objects.hash(id
);
}
}

참고로 id는 @GeneratedValue를 사용하여 생성되도록 하였다. 

나머지는 @Column annotation을 사용하여 nullable 여부와 length를 표시해주었다.