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

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1A @MappedSuperclass shares columns and behavior with entities without being an entity itself.
  2. 2JPA lifecycle callbacks let you populate fields at persist and update time with no service code.
  3. 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.

Auditing timestamps with a JPA MappedSuperclass in Spring — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code