Say you want to keep some simple audit data on your records, like:
-
create date
-
update date
-
create by
-
update by
Good news: Spring Boot already gives us a clean way to do this. Let me show you how I set it up.
Step 0 — Make sure you have JPA in your pom.xml
First things first, you need the JPA starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Step 1 — Create Auditor.java
This little class tells Spring who the current user is, so it can fill in the “create by” and “update by” fields:
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 — Turn on auditing in your application class
Add @EnableJpaAuditing and define the 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 the listener to your base entity
Add @EntityListeners and @MappedSuperclass to a base entity, and drop in the audit fields:
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 — Extend BaseEntity
Now any entity that extends BaseEntity gets those audit fields for free:
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;
}
That’s all there is to it. From now on, whenever you save through JPA, Spring Boot fills in the audit data for you automatically.