Auditing - 엔티티의 생성 변경 기록
엔티티를 생성과 변경을 할 때 변경을 한 사람, 시간 기록을 남겨두면 운영 과정에서 훨씬 도움이 될 것이다.
순수 JPA에서의 Auditing
1. JpaBaseEntity라는 날짜 속성을 알려주는 엔티티를 만든다.
@Getter
@MappedSuperclass // 진짜 상속은 아니고 선언된 속성들만 사용한다는 것
public class JpaBaseEntity {
@Column(updatable = false)
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
@PrePersist
public void prePersist() {
LocalDateTime now = LocalDateTime.now();
createdDate = now;
updatedDate = now;
}
@PreUpdate
public void preUpdate() {
updatedDate = LocalDateTime.now();
}
}
2. Member 엔티티에서 JpaBaseEntity를 상속 받는다.
public class Member extends JpaBaseEntity {
....
}
3. 테스트에서 실행해보면 만든 날짜와 수정 날짜가 나온다.
@Test
public void JpaEventBaseEntity() throws Exception {
//given
Member member = new Member("member1");
memberRepository.save(member); // @PerPersist 발생
Thread.sleep(100);
member.setUsername("member2");
em.flush(); // @PreUpdate
em.clear();
//when
Member findMember = memberRepository.findById(member.getId()).get();
//then
System.out.println("findMember.getCreatedDate = " + findMember.getCreatedDate());
System.out.println("findMember.getUpdatedDate = " + findMember.getUpdatedDate());
}
콘솔 결과 창
findMember.getCreatedDate = 2023-08-12T14:36:13.643212
findMember.getUpdatedDate = 2023-08-12T14:36:13.795051
장점은 모든 엔티티에 JpaBaseEntity를 상속 시킬 수 있다. Team의 수정시간을 보고 싶을 때에도 팀에 JpaBaseEntity를 상속 시키면 되니까 엔티티별로 따로 만들 필요가 없다.
스프링 데이터 JPA 사용
1. Main 클래스에 무조건 @EnableJpaAuditing 어노테이션 넣어줘야 함
@EnableJpaAuditing // 필수!
@SpringBootApplication
public class DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}
}
2. BaseEntity 클래스 생성
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
생성 날짜는 @CreatedDate, 수정 날싸는 @LastModifiedDate로 한다.
@EntityListeners(AuditingEntityListener.class)는 변경이 있을 때만 동작한다는 어노테이션? 그런 의미이다.
3. Member의 상속 엔티티 교체
public class Member extends BaseEntity {
....
}
이후의 작업은 나머지와 동일한데 스프링 데이터 JPA를 사용하니 훨씬 간편해졌다.
- 날짜 뿐만 아니라 변경한 사용자도 알려주기
1. BaseEntity에 엔티티 추가
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Column(updatable = false)
private String createBy;
@LastModifiedBy
private String lastModifiedBy;
}
@CreatedBy는 생성한 사람, @LastModifiedBy는 수정한 사람을 칭한다.
2. 메인 클래스에 스프링 빈 주입
@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of(UUID.randomUUID().toString());
// 원래는 스프링 시큐리티에서 세션을 꺼낸 다음에 그 id를 넣어줘야 한다.
}
}
auditorProvier()라는 스프링 빈을 주입한다. 원래는 UUID 값이 아니라 스프링 시큐리티나 http에서 세션을 꺼낸 다음 그 사람의 id를 넣어줘야 하는데, 지금은 예제니까 UUID를 사용했다.
3. 테스트
@Test
public void JpaEventBaseEntity() throws Exception {
//given
Member member = new Member("member1");
memberRepository.save(member); // @PerPersist 발생
Thread.sleep(100);
member.setUsername("member2");
em.flush(); // @PreUpdate
em.clear();
//when
Member findMember = memberRepository.findById(member.getId()).get();
//then
System.out.println("findMember.getCreatedDate = " + findMember.getCreatedDate());
System.out.println("findMember.getUpdatedDate = " + findMember.getLastModifiedDate());
System.out.println("findMember.getCreatedBy = " + findMember.getCreateBy());
System.out.println("findMember.getUpdatedBy = " + findMember.getLastModifiedBy());
}
테스트를 해보면 시간 이외에 생성, 변경한 사람의 UUID도 출력해준다.
콘솔 결과 창
findMember.getCreatedDate = 2023-08-12T14:49:40.986619
findMember.getUpdatedDate = 2023-08-12T14:49:41.130150
findMember.getCreatedDate = d63da64a-e66c-48da-b173-4a940a7a4672
findMember.getUpdatedDate = 9dd20bcb-dd73-42e2-ae4c-5f5615c961e8