What are the four JPA auditing annotations in Spring Data, and what two things must you configure to make them populate automatically?
answer
- 4 annotations: CreatedDate/LastModifiedDate/CreatedBy/LastModifiedBy
- @EnableJpaAuditing turns it on globally
- @EntityListeners(AuditingEntityListener.class) on entity
- dates auto; who needs AuditorAware
- @MappedSuperclass base class idiom
basics
~10 sThe annotations are @CreatedDate, @LastModifiedDate, @CreatedBy, and @LastModifiedBy on entity fields. To activate them you add @EnableJpaAuditing on a config class and attach @EntityListeners(AuditingEntityListener.class) to the entity.
solid answer
~30 sSpring Data JPA fills four fields for you: @CreatedDate and @LastModifiedDate (timestamps) and @CreatedBy and @LastModifiedBy (the acting principal). Two pieces wire this up. First, @EnableJpaAuditing on any @Configuration class turns the feature on globally. Second, each audited entity needs @EntityListeners(AuditingEntityListener.class), which registers the JPA listener that sets those fields during persist and update lifecycle callbacks. Dates work out of the box; the @CreatedBy/@LastModifiedBy fields stay null unless you also provide an AuditorAware<T> bean that returns the current user. You typically put the four fields on a shared @MappedSuperclass base class so every entity inherits them without repetition.
code
java · 29 lines@Configuration
@EnableJpaAuditing
class JpaAuditingConfig { }
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {
@CreatedDate
@Column(updatable = false)
private Instant createdDate;
@LastModifiedDate
private Instant lastModifiedDate;
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
// getters/setters
}
@Entity
public class Article extends Auditable {
@Id @GeneratedValue Long id;
String title;
}go deeper
Name the four annotations and the two wiring steps (@EnableJpaAuditing + @EntityListeners); know dates auto-fill.
Add that @CreatedBy needs AuditorAware, and that the @MappedSuperclass base class is the standard placement.
Discuss updatable=false on created columns, correct field types, and the org.springframework.data.annotation package distinction.
Frame auditing as one option among Envers, DB triggers, and event-sourcing; know its consistency and testability trade-offs.
## What auditing metadata is "Auditing" here means automatically recording *who* touched a row and *when*, without writing that code in every service. Spring Data JPA provides four field-level annotations: - **`@CreatedDate`** — set once, when the entity is first persisted (INSERT). - **`@LastModifiedDate`** — set on the initial persist and re-set on every update. - **`@CreatedBy`** — the principal (user) who created the row, set once. - **`@LastModifiedBy`** — the principal who last modified the row, re-set on every update. All four live in package `org.springframework.data.annotation` (note: *not* the JPA package), so they are Spring Data annotations, not standard JPA. ## The two required wiring steps **1. Enable the feature.** Put `@EnableJpaAuditing` on a `@Configuration` class (often the main application class). This registers the infrastructure beans that make auditing work. Without it, the annotations are simply ignored. **2. Register the listener on the entity.** Annotate each audited entity with `@EntityListeners(AuditingEntityListener.class)`. `AuditingEntityListener` is a JPA entity listener that hooks the `@PrePersist` and `@PreUpdate` lifecycle events and writes the four fields at those moments. ## Field types - Date/time fields may be `Instant`, `LocalDateTime`, `Date`, `Long` (epoch millis), or Java 8 date types — Spring converts appropriately. - `@CreatedBy`/`@LastModifiedBy` are typed to whatever your `AuditorAware<T>` returns — commonly `String` (username) or a `Long`/`UUID` user id. ## The auditor piece Timestamps need no extra config — the framework reads the clock. But *who* the current user is, Spring cannot know. You supply an `AuditorAware<T>` bean whose `getCurrentAuditor()` returns an `Optional<T>` of the current principal (typically pulled from Spring Security's `SecurityContextHolder`). If you omit it, `@CreatedBy`/`@LastModifiedBy` stay null but timestamps still populate. ## Where to put the fields Repeating four fields on every entity is noise. The idiom is a `@MappedSuperclass` base class (e.g. `Auditable`) holding the four fields plus `@EntityListeners(AuditingEntityListener.class)`, which all entities extend. `@MappedSuperclass` means the base's columns are mapped into each subclass's table without the base being an entity itself. ## Common gotchas - Forgetting `@EnableJpaAuditing` — fields silently stay null. - Forgetting `@EntityListeners` on the entity (or on the base class) — same silent null. - Expecting `@CreatedBy` to fill without an `AuditorAware` bean. - Using `save()` on a *detached/merge* path and expecting `@CreatedDate` — created is only set on the first persist.
- Which import package do @CreatedDate and friends come from, and why does it matter?org.springframework.data.annotation — they are Spring Data annotations, not jakarta.persistence. Importing the wrong same-named type (there isn't a JPA equivalent, but IDEs sometimes auto-import odd things) means nothing populates.
- If you enable auditing but never define an AuditorAware bean, what happens?Timestamps (@CreatedDate/@LastModifiedDate) still populate from the clock, but @CreatedBy/@LastModifiedBy stay null because Spring has no source for the current principal.
saying these in an interview costs you the question
- Thinking @EnableJpaAuditing alone is enough without @EntityListeners on the entity
- Believing the annotations come from jakarta.persistence / standard JPA
- Assuming @CreatedBy fills automatically without an AuditorAware bean
- Confusing this with Hibernate Envers (which is full row-versioning/history, a different feature)