java 56 lines · 7 steps

Automatic audit trails with Spring Data JPA

Wire JPA auditing to your security context so every record stamps who created it and when, with no manual bookkeeping.

Explained by highlit
1@Configuration
2@EnableJpaAuditing(auditorAwareRef = "auditorAware")
3public class AuditingConfig {
4 
5 @Bean
6 public AuditorAware<String> auditorAware() {
7 return () -> Optional.ofNullable(SecurityContextHolder.getContext())
8 .map(SecurityContext::getAuthentication)
9 .filter(Authentication::isAuthenticated)
10 .filter(auth -> !(auth instanceof AnonymousAuthenticationToken))
11 .map(Authentication::getName)
12 .or(() -> Optional.of("system"));
13 }
14}
15 
16@Entity
17@Table(name = "audit_records")
18@EntityListeners(AuditingEntityListener.class)
19public class AuditRecord {
20 
21 @Id
22 @GeneratedValue(strategy = GenerationType.UUID)
23 private UUID id;
24 
25 @Enumerated(EnumType.STRING)
26 @Column(nullable = false, updatable = false)
27 private AuditAction action;
28 
29 @Column(nullable = false, updatable = false)
30 private String entityType;
31 
32 @Column(nullable = false, updatable = false)
33 private String entityId;
34 
35 @Column(columnDefinition = "jsonb", updatable = false)
36 @JdbcTypeCode(SqlTypes.JSON)
37 private Map<String, Object> details;
38 
39 @CreatedBy
40 @Column(name = "performed_by", nullable = false, updatable = false)
41 private String performedBy;
42 
43 @CreatedDate
44 @Column(name = "performed_at", nullable = false, updatable = false)
45 private Instant performedAt;
46 
47 protected AuditRecord() {
48 }
49 
50 public AuditRecord(AuditAction action, String entityType, String entityId, Map<String, Object> details) {
51 this.action = action;
52 this.entityType = entityType;
53 this.entityId = entityId;
54 this.details = details;
55 }
56}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1An AuditorAware bean lets JPA resolve the current user automatically at persist time.
  2. 2Marking audit columns updatable=false enforces that records are append-only.
  3. 3Entity listeners plus @CreatedBy/@CreatedDate remove hand-written audit plumbing entirely.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Automatic audit trails with Spring Data JPA — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code