Spring Data JPA에는 Auditing 기능을 편하게 다룰 수 있도록 @CreatedDate, @LastModifiedDate 어노테이션을 제공해준다. 그리고 생성일자, 수정일자 컬럼은 웬만한 모든 도메인에 있으면 로깅 및 사용자 입장에서도 간편하다. 따라서 보통 BaseEntity라는 생성일자, 수정일자가 들어있는 상위 엔티티를 만들고 상속 구조를 이용하는 방법을 진행한다. 이번 포스팅에서는 이 방법에 대해 기록해보려 한다.
개발환경
- Spring Boot 2 버전
- Spring Data JPA
- lombok
프로덕션 코드
BaseEntity
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
abstract public class BaseEntity {
@CreatedDate
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
@Column(name = "last_modified_at", nullable = false)
private LocalDateTime lastModifiedDate;
}
- 이벤트를 감지하여 생성일시와 수정일시를 체크해줄 수 있도록 Spring Data JPA에서 제공해주는@EntityListeners(AuditingEntityListener.class) 어노테이션을 추가했다.
- 생성일자는 수정이 불가하도록 @Column(updatable = false) 어노테이션을 추가했다.
- 각 엔티티는 위 BaseEntity를 상속받는다.
- 해당 클래스는 인스턴스로 생성하지 못하도록 abstract로 막아두었다.
BaseEntity를 각 엔티티에서 상속받도록 한다면 위와 같은 형태가 될 것이고, 각 엔티티에는 extends 키워드를 사용하여 BaseEntity를 상속받도록 해주자. 그럼 자동으로 DB Table에 created_at, last_modified_at 컬럼이 추가되며, default값으로는 LocalDateTime.now()가 들어가게 된다.
또한, SpringBootApplication에 @EnableJpaAuditing 어노테이션을 추가해주어 Jpa Auditing 기능을 사용할 수 있도록 해주어야 한다. 메인 클래스에선 Config 어노테이션을 지양하는 편이 좋기 때문에 config 패키지에 클래스를 하나 만들어서 아래와 같이 작업해주자.
JpaAuditingConfig
@Configuration
@EnableJpaAuditing
public class JpaAuditingConfig {
}
@Configuration 어노테이션을 걸어주어 스프링 빈으로 관리하게 해놓았다.
테스트 코드
Jpa Auditing을 테스트하기 위해선 DB에 저장되고 수정이 일어났을 때를 바탕으로 진행돼야 하기 때문에 Repository 테스트로 진행하였다.
생성일자 테스트
@Test
@DisplayName("회원을 생성할 때 생성일자가 올바르게 나온다.")
void createMemberWhen() {
final Member member = new Member("alex", "alex@naepyeon.com", "abc12345");
final Long memberId = memberRepository.save(member);
final Member actual = memberRepository.findById(memberId)
.orElseThrow();
assertThat(actual.getCreatedDate()).isAfter(LocalDateTime.MIN);
}
회원이 DB에 저장될 때의 시각이 생성일자이므로, 위와 같이 DB에 회원을 저장하고 JUnit
문법의 isAfter
로 생성일자가 잘 생성됐는지 테스트했다.
수정일자 테스트
@Test
@DisplayName("회원 정보를 수정할 때 수정일자가 올바르게 나온다.")
void updateMemberWhen() {
final Member member = new Member("alex", "alex@naepyeon.com", "abc12345");
final Long memberId = memberRepository.save(member);
em.flush();
member.changeUsername("kth990303");
em.flush();
final Member actual = memberRepository.findById(memberId)
.orElseThrow();
assertThat(actual.getLastModifiedDate()).isAfter(actual.getCreatedDate());
}
회원을 저장한 후에, 이름을 수정하고 Flush하여 업데이트가 반영되도록 하였다. Repository Test는 @SpringBootTest
어노테이션이 붙어져있었기 때문에 @Autowired
로 EntityManager를 호출할 수 있었다. 수정일시가 생성일시보다 이후일 경우에 테스트가 통과되도록 설정했다.
위와 같이 Spring Data JPA에서의 Auditing 기능을 이용해 각 도메인의 변경을 최소화하여 생성일자와 수정일자 컬럼을 추가할 수 있었다.
'JAVA > JPA 학습기록' 카테고리의 다른 글
[JPA] 쓰기 지연으로 인한 쿼리 실행 시점과 예외처리 및 기본키 생성 전략 (2) | 2022.09.10 |
---|---|
[JPA] Spring Data JPA 페이징 기법을 적용해보자 (0) | 2022.08.04 |
[JPA] 양방향 연관관계에서 JPA 내부 작동 원리_영속성 컨텍스트의 이해 (0) | 2022.06.23 |
[H2] 맥에서 H2 database 실행하기 (feat. zsh: permission denied: ./h2.sh) (4) | 2022.06.15 |
[JPA] 자바 ORM 표준 JPA 프로그래밍 - 기본편 후기 (0) | 2021.10.26 |