Spring Data JPA가 제공하는 Audit 기능을 알아보자. Audit은 주로 DB값이 변경했을 때 누가 값을 변경했고, 언제 변경했는지 Audit(감사)하는 용도로 사용한다. Spring Data JPA는 @CreatedDate
, @LastModifiedDate
, @CreatedBy
, @LastModifiedBy
와 같은 어노테이션을 제공한다.
1. @EnableJpaAuditing 추가
@EnableJpaAuditing
어노테이션을 RootClass의 최 상단에 추가한다.
@SpringBootApplication
@EnableJpaAuditing
public class Application {
// 생략
}
2. 해당 Entity에 AuditingEntityListener
를 등록
해당 엔티티에 클래스 레벨에 @EntityListeners
를 선언하고,AuditingEntityListner
를 등록한다.
@Data
@Entity
// 엔티티 리스너 등록
@EntityListeners(AuditingEntityListener.class)
public class Comment {
@Id
@GeneratedValue
private Long id;
private String comment;
3. Audit할 날짜 필드를 정의한다.
해당 엔티티에 Audit을 할 필드를 정의한다. (생성일,수정일 )
// Audit 날짜 field를 정의한다.
@CreatedDate
private Date createdDate;
@LastModifiedDate
private Date lastModifiedDate;
4. Audit하는 작성자 필드를 정의한다.
// Audit 작성자 field를 정의한다.
@CreatedBy
@ManyToOne
private Account createdBy;
@LastModifiedBy
@ManyToOne
private Account updatedBy;
DB의 변경사항을 일으키는 Author를 Account클래스의 객체와 매핑했다.
Account 클래스는 다음과 같다.
@Entity
@Data
public class Account {
@Id
@GeneratedValue
private Long id;
private String username;
private String password;
}
@CreatedBy
와 @LastModifiedBy
는 Spring Security의 ContextHolder안에 들어있는 Principal(신원정보)의 name값으로 매핑을 해준다.
만약에 Custom하게 구현할려면 아래와 같이 AuditorAware 인터페이스를 구현해야 한다.
Spring Security의 ContextHolder에 존재하는 Authentication 정보를 통해서 매핑한다.
@Service
public class AccountAwareAudit implements AuditorAware<Comment> {
@Override
public Optional<Comment> getCurrentAuditor() {
// Spring Security를 통한 Auditor 매핑
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return ((MyUserDetails) authentication.getPrincipal()).getUser();
}
이렇게 만든 빈(AccountAwareAudit)을 참조할 수 있도록 @EnableJpaAuditing의 auditorAwareRef 속성값으로 등록 해준다.
@SpringBootApplication
@EnableJpaAuditing(auditorAwareRef = "accountAwareAudit")
public class Application {
// 생략
}
5. 정리
Spring Data Jpa가 제공하는 엔티티의 변화를 추적하는 Audit 기능에 대해서 알아보았다. 날짜 Audit은 제공해준 어노테이션 기반으로 구현할 부분이 없었지만, 작성자에 관한 부분은 대부분 Spring Security를 사용하기 때문에 ContextHolder를 통해서 신원정보를 가져와서 매핑해 주었다.
6. 참고자료
📚 Related Posts
- JPA - 값 타입(6)
- JPA - 프록시와 연관관계(5)
- JPA - 다양한 연관관계 매핑(4)
- JPA - 연관관계 매핑(기초)(3)
- JPA - 엔티티 매핑(2)
- JPA - 영속성 관리(1)
- [JPA] 연관관계 매핑 (연관관계 편의 메서드)
- [JPA] 엔티티 설계시 주의사항들
- [JPA] Auditing 사용하기
- [JPA]@Transactional를 통한 Optimization
- [JPA] 엔티티 일부 데이터만 조회하는 Projection
- [JPA] save메서드로 살펴보는 persist와 merge 개념
- [JPA] 쿼리메서드(Lookup 전략)
- [JPA] QueryDSL 설정방법
- [JPA] null 처리
- [JPA] 연관관계 매핑 기초(다대일, 연관관계 주인)
- SpringBoot, JPA, H2를 이용한 간단한API 작성
- [JPA] proxy, fetch 전략
- [JPA] 도메인 클래스 컨버터란?
- [JPA] Custom Repository 만들기
- [JPA] Casecade 옵션