Spring Boot + JPA + Audit Listener
Nov 11, 2020
Let’s say we need to keep simple Audit data like:
- create date
- update date
- create by
- update by
Spring Boot is already provided this solution for us.
Step 0 — Make sure you have JPA in your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Step 1 — Create Auditor.java
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Optional;
public class Auditor implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
return authentication != null ? Optional.of((String) authentication.getPrincipal()) : Optional.of("0");
}
}
It’s depends on your Principal object type you use.
This example use String to represent user id as Principal
Step 2— Add @EnableJpaAuditing and define Audit Bean in your Spring Boot application class
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing(auditorAwareRef = "auditor")
public class MyAwesomeApplication { ... @Bean
public AuditorAware<String> auditor() {
return new Auditor();
} ...}
Step 3 — Add @EntityListeners and @MappedSuperclass into your base entity
import lombok.Data;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.time.Instant;
@Data
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseEntity { ... @CreatedBy
@Column(length = 36)
private String createdBy;
@CreatedDate
private Instant created;
@LastModifiedBy
@Column(length = 36)
private String updatedBy;
@LastModifiedDate
private Instant updated; ...}
Step 4 — Extends BaseEntity
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@EqualsAndHashCode(callSuper = true)
@Data
@Entity(name = "m_user")
public class User extends BaseEntity {
@Column(length = 60, nullable = false, unique = true)
private String username;
}
When saving via JPA, Spring Boot will be saved Audit Data for you automatically.