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
@Component @Converter public class EncryptedStringConverter implements AttributeConverter<String, String> {
Transparent column encryption in Spring & JPA
encryption
aes-gcm
jpa-converter
Advanced
10 steps
java
package com.acme.billing.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties;
Feature-flagged beans with Spring @ConditionalOnProperty
feature-flags
conditional-beans
strategy-pattern
Intermediate
5 steps
java
public static Map<String, String> parseCookieHeader(String header) { Map<String, String> cookies = new LinkedHashMap<>(); if (header == null || header.isBlank()) { return cookies;
Parsing an HTTP Cookie header in Java
string-parsing
http
url-decoding
Intermediate
6 steps
java
public class TimedSocketReader { private static final int READ_TIMEOUT_MS = 5_000; private static final int CONNECT_TIMEOUT_MS = 3_000;
Reading a socket with connect and read timeouts
sockets
timeouts
io
Intermediate
8 steps
java
public final class EncodingDetector { public enum Encoding { UTF_8, UTF_16LE, UTF_16BE, UTF_32LE, UTF_32BE, ASCII, UNKNOWN
Detecting text encoding from raw bytes in Java
byte-manipulation
encoding-detection
bitwise-operations
Intermediate
8 steps
java
public final class ImportOrganizer { private static final Pattern IMPORT_LINE = Pattern.compile("^import\\s+(static\\s+)?([\\w.]+(?:\\.\\*)?)\\s*;\\s*$");
Sorting Java imports with a regex pass
regex
sorting
text-processing
Intermediate
8 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.