Auditing
엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶을 때
- 등록일
- 수정일
- 등록자
- 수정자
먼저 순수 JPA를 사용하여 등록일, 수정일을 추가할 수 있도록 해보자.
먼저 아래와 같이 수정일과 등록일을 위한 엔티티가 필요하다. (@MappedSuperclass 사용 )
@Getter
@MappedSuperclass
public class JpaBaseEntity {
@Column(updatable = false)//생성일은 변경될 수 없다.
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
@PrePersist//Persist하기 전에 호출
public void prePersist(){
LocalDateTime now = LocalDateTime.now();
createdDate = now;
updatedDate = now;
}
@PreUpdate//Update하기 전에 호출
public void preUpdate(){
updatedDate = LocalDateTime.now();
}
}
등록일과 수정일을 추가하고 싶은 엔티티가 위의 JpaBaseEntity를 extends하면 된다.
public class Member extends JpaBaseEntity{ /* extends JpaBaseEntity */
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
private String username;
private int age;
@ToString.Exclude
@JoinColumn(name="team_id")
@ManyToOne(fetch=FetchType.LAZY)
private Team team;
/// 중략... ///
}
이제 이를 테스트해보자.
@Test
void JpaEventBaseEntity() throws Exception {
//given
Member member = new Member("member1", 10, null);
memberRepository.save(member); /* @PrePersist 발동 */
Thread.sleep(1000);//1초 지연
member.setUsername("멤버1");
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() = 2022-01-08T14:12:04.955749
findMember.getUpdatedDate() = 2022-01-08T14:12:05.982232
DB에도 잘 반영된 것을 볼 수 있다.
하지만 데이터 JPA는 위와 같은 기능을 더 쉽게 제공한다.
데이터 JPA로 Auditing
이를 위해서는 먼저 아래의 설정을 메인 클래스에 해줘야 한다.
@EnableJpaAuditing
@EnableJpaAuditing /* 요 어노테이션 잊지 말자! */
@SpringBootApplication
public class DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}
}
이제 Base 엔티티를 만들어보자.
@EntityListeners(AuditingEntityListener.class) // 이벤트 기반으로 동작한다!
@Getter
@MappedSuperclass
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}
@CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy 와 같은 어노테이션들을 제공한다.
또한 @EntityListeners 어노테이션도 잊지 말자.
그리고 @CreatedBy, @LastModifiedBy와 같은 기능을 사용하기 위해서는 아래와 같이 생성자, 작성자 아이디를 반환해주는 메서드가 필요하다.
@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}
@Bean /* @CreatedBy, @LastModifiedBy를 위해 필요하다. */
public AuditorAware<String> auditorProvider(){
return () -> Optional.of(UUID.randomUUID().toString());
}
}
이를 테스트 해보자.
@Test
void JpaEventBaseEntity() throws Exception {
//given
Member member = new Member("member1", 10, null);
memberRepository.save(member); /* @PrePersist 발동 */
Thread.sleep(1000);//1초 지연
member.setUsername("멤버1");
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.getLastModifiedDate() = " + findMember.getLastModifiedDate());
System.out.println("findMember.getCreatedBy() = " + findMember.getCreatedBy());
System.out.println("findMember.getLastModifiedBy() = " + findMember.getLastModifiedBy());
}
실행결과:
findMember.getCreatedDate() = 2022-01-08T14:41:29.694353
findMember.getLastModifiedDate() = 2022-01-08T14:41:30.722636
findMember.getCreatedBy() = 4e31bd4a-08d7-4a73-92d4-09e6958c7254
findMember.getLastModifiedBy() = 7e1fcd67-34bc-4980-9262-ad8fcd83c6cb
+ 추가
그런데 만약 어떤 엔티티에서는 생성일과 수정일은 필요하지만 작성자와 수정자는 불필요할 수 있다. 하여 이러한 상황에서는 아래와 같이 한다.
생성일, 수정일 BaseEntity를 만들고,
@EntityListeners(AuditingEntityListener.class) // 이벤트 기반으로 동작한다!
@Getter
@MappedSuperclass
public class DateBaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
이를 BaseEntity가 상속하여 생성자와 수정자를 추가한다.
@EntityListeners(AuditingEntityListener.class) // 이벤트 기반으로 동작한다!
@Getter
@MappedSuperclass
public class BaseEntity extends DateBaseEntity{
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}
이제 생성일과 수정일만 필요한 엔티티는 DateBase엔티티를 상속받고, 더불어 생성자와 수정자까지 필요한 엔티티는 BaseEntity를 상속받으면 되는 것이다.
김영한님의 인프런 강의와 PDF를 바탕으로 정리하였습니다.
'JPA > 스프링 DATA JPA' 카테고리의 다른 글
Data JPA 13 - 스프링 데이터 JPA 분석 (0) | 2022.01.11 |
---|---|
Data JPA 12 Web확장 : 도메인 클래스 컨버터, 페이징과 정렬 (0) | 2022.01.09 |
Data JPA 10 사용자 정의 리포지토리 구현 (0) | 2022.01.08 |
Data JPA 09 JPA Hint (0) | 2022.01.08 |
Data JPA 08 @EntityGraph (0) | 2022.01.07 |