java
42 lines · 5 steps
Auditing timestamps with a JPA MappedSuperclass in Spring
A reusable base class stamps created_at and updated_at automatically using JPA lifecycle callbacks.
Explained by
highlit
1package com.acme.catalog.persistence;
2
3import jakarta.persistence.Column;
4import jakarta.persistence.EntityListeners;
5import jakarta.persistence.MappedSuperclass;
6import jakarta.persistence.PrePersist;
7import jakarta.persistence.PreUpdate;
8import java.time.Instant;
9
10@MappedSuperclass
11@EntityListeners(Auditable.AuditListener.class)
12public abstract class Auditable {
13
14 @Column(name = "created_at", nullable = false, updatable = false)
15 private Instant createdAt;
16
17 @Column(name = "updated_at", nullable = false)
18 private Instant updatedAt;
19
20 public Instant getCreatedAt() {
21 return createdAt;
22 }
23
24 public Instant getUpdatedAt() {
25 return updatedAt;
26 }
27
28 static class AuditListener {
29
30 @PrePersist
31 void onCreate(Auditable entity) {
32 Instant now = Instant.now();
33 entity.createdAt = now;
34 entity.updatedAt = now;
35 }
36
37 @PreUpdate
38 void onUpdate(Auditable entity) {
39 entity.updatedAt = Instant.now();
40 }
41 }
42}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A @MappedSuperclass shares columns and behavior with entities without being an entity itself.
- 2JPA lifecycle callbacks let you populate fields at persist and update time with no service code.
- 3Making created_at non-updatable protects the original creation moment from later writes.
Related explainers
java
@Configuration public class WebConfig { @Bean
HTTP caching with ETags in Spring
http-caching
etag
servlet-filters
Intermediate
6 steps
java
@Service @RequiredArgsConstructor public class ExchangeRateService {
Request-scoped rate caching in Spring
request-scope
caching
memoization
Advanced
6 steps
ruby
class Admin::AccountsController < Admin::BaseController before_action :set_account, only: :destroy def destroy
A guarded destroy action in Rails
controllers
callbacks
transactions
Intermediate
8 steps
java
public final class CircuitBreaker { private enum State { CLOSED, OPEN, HALF_OPEN }
How a circuit breaker guards failing calls
state-machine
resilience
concurrency
Advanced
7 steps
java
public Map<Long, CustomerDto> indexByCustomerId(List<CustomerDto> customers) { return customers.stream() .collect(Collectors.toMap( CustomerDto::getId,
Building maps from lists with Collectors.toMap
streams
collectors
maps
Intermediate
5 steps
java
@Service public class InventoryService { private final RestClient warehouseClient;
Bulkhead-protected HTTP calls in Spring
bulkhead
resilience
fallback
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/auditing-timestamps-with-a-jpa-mappedsuperclass-in-spring-explained-java-45f2/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.