Recording the User with AuditorAware

Who Made the Change

@CreatedBy and @LastModifiedBy are filled from an AuditorAware<T> bean that returns the current user. With Spring Security, read it from the SecurityContext (see the Spring Security material).

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class JpaConfig {

    @Bean
    AuditorAware<String> auditorProvider() {
        return () -> Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getName)
                .or(() -> Optional.of("system"));        // batch jobs, schedulers
    }
}

A Reusable Base Class

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {

    @CreatedDate      @Column(nullable = false, updatable = false) private Instant createdAt;
    @LastModifiedDate @Column(nullable = false)                    private Instant updatedAt;
    @CreatedBy        @Column(nullable = false, updatable = false) private String createdBy;
    @LastModifiedBy   @Column(nullable = false)                    private String updatedBy;

    // getters only
}

@Entity @Table(name = "orders")
public class Order extends Auditable { ... }       // gets all four columns
create table orders (
    id bigint not null auto_increment,
    created_at datetime(6) not null,
    created_by varchar(255) not null,
    updated_at datetime(6) not null,
    updated_by varchar(255) not null,
    status enum ('CANCELLED','CREATED','DELIVERED','PAID','SHIPPED'),
    total decimal(38,2),
    user_id bigint not null,
    primary key (id)
) engine=InnoDB;

Testing Time

Tip: Spring Data uses a DateTimeProvider for @CreatedDate. Register one with @EnableJpaAuditing(dateTimeProviderRef = "auditingDateTimeProvider") backed by a Clock bean, and inject Clock.fixed(...) in tests to get predictable timestamps.