JPA Auditing으로 생성시간/수정시간 자동화하기
엔티티(Entity)에는 해당 데이터의 생성시간과 수정시간을 포함해야 한다.
언제 만들어졌는지, 언제 수정되었는지 등은 차후 유지보수에 있어 중요한 정보이기 때문이다.
그렇다 보니 매번 DB에 삽입하기 전, 생성하기 전에 날짜 데이터를 등록/수정하는 코드가 들어가게 된다.
//생성일 추가 코드 예제
public void savePosts(){
...
posts.setCreateDate(new LocalDate());
postsRepository.save(posts);
...
}
이렇게 반복적으로 코드가 모든 테이블과 서비스 매소드에 포함되어야 한다면 번거롭고, 지저분한 코드가 된다.
이 문제는 JPA Auditing을 사용하여 해결 할 수 있다.
JPA에서는 Audit이라는 기능을 제공하고 있다. Audit은 감시하다, 감사하다라는 뜻으로 Spring Data JPA에서 시간에 대해서 자동으로 값을 넣어주는 기능이다.
이 클래스는 모든 엔티티의 상위 클리스가 되어 엔티티들의 createDate, modefiedDate를 자동으로 관리하는 역할을 한다.
package com.spring.book.domain;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass //(1)
@EntityListeners(AuditingEntityListener.class) //(2)
public class BaseTimeEntity {
@CreatedDate //(3)
private LocalDateTime createdDate;
@LastModifiedDate //(4)
private LocalDateTime modifiedDate;
}
(1) @MappedSuperclass
JPA 엔티티 클래스들이 BaseTimeEntity를 상속할 경우 필드들(createdDate, modifiedDate)도 칼럼으로 인식하도록 한다.
(2) @EntityListeners(AuditingEntityListener.class)
BaseTimeEntity 클래스에 Auditing 기능을 포함시킨다.
(3) @CreatedDate
엔티티가 생성되어 저장될 때 시간이 자동으로 저장된다.
(4) @LastModifiedDate
조회한 엔티티의 값을 변경할 때 시간이 자동 저장된다.
...
public class Posts extends BaseTimeEntity {
...
}
마지막으로 Application 클래스에 활성화 어노테이션(@EnableJpaAuditing
)을 추가하면 JPA Auditing 어노테이션들을 모두 활성화된다.
@EnableJpaAuditing
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Test
public void BaseTimeEntity_등록(){
//given
LocalDateTime now = LocalDateTime.of(2022,10,16,3,33,0);
postsRepository.save(Posts.builder()
.title("title")
.content("content")
.author("author")
.build());
//when
List<Posts> postsList = postsRepository.findAll();
//then
Posts posts = postsList.get(0);
System.out.println(">>>>>>>>> createDate=" + posts.getCreatedDate() + ", modifiedDate=" + posts.getModifiedDate());
assertThat(posts.getCreatedDate().isAfter(now));
assertThat(posts.getModifiedDate().isAfter(now));
}
...
2022-10-16 15:39:49.326 INFO 1637 --- [ main] c.s.b.domain.posts.PostRepositoryTest : Started PostRepositoryTest in 1.517 seconds (JVM running for 1.884)
Hibernate: insert into posts (created_date, modified_date, author, content, title) values (?, ?, ?, ?, ?)
Hibernate: select posts0_.id as id1_0_, posts0_.created_date as created_2_0_, posts0_.modified_date as modified3_0_, posts0_.author as author4_0_, posts0_.content as content5_0_, posts0_.title as title6_0_ from posts posts0_
>>>>>>>>> createDate=2022-10-16T15:39:49.407562, modifiedDate=2022-10-16T15:39:49.407562
...
테스트 코드를 수행해 보면 시간이 잘 저장되는 것을 확인할 수 있다.