생성일, 수정일 같은 중요한 정보를 기록하는 코드가 모든 테이블과 서비스 메소드에 반복적으로 작성된다면, 귀찮고 자칫 코드가 지저분해질 수 있다.
이런 문제를 해결하고자 JPA Auditing을 사용해 보려고 한다.
JPA Auditing은 JPA를 사용하여 엔티티의 생성일, 수정일 같은 정보를 자동으로 기록하고 추적하는 기능인데, 일반적으로 Spring Data JPA와 함께 사용된다.
JPA Auditing을 구련하려면 엔티티에 @EntityListeners
어노테이션을 사용하여 리스너를 등록해야 한다. 이 리스너는 엔티티의 상태가 변경될 때 마다 콜백 메소드를 호출하여 적절한 정보를 추적하고 기록한다.
JPA Auditing 기능을 사용하기 위해 다음과 BaseTime엔티티를 생성한다.
@Getter
@EnableJpaAuditing
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime modifiedDate;
}
잠시 위의 코드를 설명해보자면
@EnableJpaAuditing
JPA Auditing 어노테이션들을 모두 활성화 시키는 어노테이션
@MappedSuperClass
JPA 어노테이션. 엔티티에서 공통적으로 사용하는 필드를 정의하는 추상 클래스임을 나타낸다. 즉, JPA Entity 클래스들이 BaseTimeEntity를 상속할 경우 필드들(createdDate, modifiedDate)도 컬럼으로 인식하도록 한다.
@EntityListeners(AuditingEntityListener.class)
JPA Auditing을 구현하기 위한 어노테이션 중 하나로, BaseEntity 클래스에서 리스너를 사용하도록 설정한다.
@CreatedDate
Entity가 생성되어 저장될 때 시간이 자동으로 저장된다.
@LastModifiedDate
조회된 Entity의 값을 변경할 때 시간이 자동으로 저장된다.
위와 같이 실제 구현 코드를 완성시켰으니, 이제 제대로 작동하는지 테스트를 해보자.
package com.myshop.domain.posts;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.LocalDateTime;
import java.util.List;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest // 별다른 설정 없이 이 어노테이션을 사용할 경우 H2 데이터베이스를 자동으로 실행해줌
public class PostsRepositoryTest {
@Autowired
PostsRepository postsRepository;
@After
public void cleanup() {
postsRepository.deleteAll();
}
@Test
public void BaseTimeEntityTest() {
//given
LocalDateTime now = LocalDateTime.of(2023,3,19,0,0,0);
postsRepository.save(Posts.builder()
.title("생성일 제목")
.content("생성일 내용")
.author("테스트~")
.build()
);
//when
List<Posts> postsLists = postsRepository.findAll();
//then
Posts posts = postsLists.get(0);
System.out.println(">>>> createdDate=" + posts.getCreatedDate()+", modifiedDate=" + posts.getModifiedDate());
assertThat(posts.getCreatedDate()).isAfter(now);
assertThat(posts.getModifiedDate()).isAfter(now);
}
}
위 테스트 코드에서는 현재 시점의 LocalDateTime 정보를 생성한다.
생성된 정보는 save 메소드로 객체를 저장할 때 BaseEntity 클래스의 생성일(createdDate)과 수정일(modifiedDate) 정보가 자동으로 기록된다.
그 후, findAll() 메소드로 저장된 리스트들을 모두 불러온 뒤, 첫번째 엔티티 객체를 선택하여 posts 변수에 저장한 후 결과를 출력한다.
마지막으로 Posts 엔티티 객체의 생성일과 수정일이 테스트시점의 LocalDateTime 정보(now) 이후임을 검증한다.
테스트코드를 실행해보면 콘솔창에 createdDate와 modifiedDate가 조회된다!
참고 : 스프링 부트와 AWS로 혼자 구현하는 웹 서비스