bigywater.tech
Spring · 94

审计:@CreatedDate 与 @LastModifiedBy

@CreatedDate 和 @LastModifiedBy 是怎么填上的?批量更新会不会更新修改时间?异步线程里用户怎么没了?忘了开 @EnableJpaAuditing 会报错吗?这篇在 Spring Boot 4.0.8、Hibernate 7、MySQL 上逐个实测。

2 个审计列
更新时发出的 update 只含 last_modified_by 和 last_modified_date
批量 update 不触发
@Modifying 的 JPQL 更新之后,lastModified 与 lastModifiedBy 都没变
createdBy = null
save 在另一个线程里执行时,AuditorAware 读不到 ThreadLocal 里的用户

基本用法

实测 · 本机执行输出
save(new Doc) 之后:Doc[t1 创建 11:38:07.780801 by alice,修改 11:38:07.780801 by alice]
    SQL:insert into doc (created_by,created_date,last_modified_by,last_modified_date,title) values (?,?,?,?,?)
    SQL:update doc set last_modified_by=?,last_modified_date=?,title=? where id=?
bob 修改之后:Doc[t1-改 创建 11:38:07.780801 by alice,修改 11:38:08.925469 by bob]

@EnableJpaAuditing 加 @EntityListeners 加四个注解;更新只改 last_modified_*。

不触发的情况

实测 · 本机执行输出
把标题改成同样的值(脏检查没发现变化):Doc[t1-改 创建 11:38:07.780801 by alice,修改 11:38:08.925469 by bob]
只读取不修改,发出的 update 条数:0
@Modifying 批量 update 改了标题(carol 操作):Doc[批量改 创建 11:38:07.780801 by alice,修改 11:38:08.925469 by bob]——lastModified 仍是旧的,lastModifiedBy 仍是 bob
实体方式再改一次(carol 操作):Doc[再改一次 创建 11:38:07.780801 by alice,修改 11:38:10.067201 by carol]

同值修改、只读取和批量 JPQL 更新都不会更新审计字段。

静默失败

实测 · 本机执行输出
没有当前用户(AuditorAware 返回 Optional.empty())时 save:Doc[无登录用户 创建 11:38:10.070898 by null,修改 11:38:10.070898 by null]
注解齐全但实体没有 @EntityListeners(AuditingEntityListener.class):DocNoListener[createdDate=null,createdBy=null]

没有当前用户或缺监听器时审计字段为 null,不报错。

线程

实测 · 本机执行输出
alice 的线程里调用,但 save 在线程池的线程里执行:Doc[在另一个线程里保存 创建 11:38:10.077368 by null,修改 11:38:10.077368 by null](AuditorAware 读的是 ThreadLocal)
在任务里自己把用户设置到那个线程:Doc[线程里先设置用户 创建 11:38:10.079174 by carol,修改 11:38:10.079174 by carol]

AuditorAware 读 ThreadLocal,线程池里的 save 读不到用户。

开关

实测 · 本机执行输出
  save 之后:Doc[t0 创建 null by null,修改 null by null](实体上有 @EntityListeners 与注解,但没开 @EnableJpaAuditing)

缺 @EnableJpaAuditing 也是静默不填。

分步演示

审计
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(Hibernate 7、Spring Data JPA 4 随 spring-boot-starter-data-jpa;MySQL 是本机自己起的 26.7.0 实例)。Doc 实体带四个审计字段(createdDate 与 createdBy 标了 updatable = false);AuditorAware 从 ThreadLocal 取用户,代替 Spring Security;时间取自应用所在机器的时钟(LocalDateTime),不是数据库的;「没开 @EnableJpaAuditing」是另一次独立运行
    • 没有验证:真实的 Spring Security 下 AuditorAware 的写法与 SecurityContext 传播;Instant、OffsetDateTime 等其他时间类型;自定义 DateTimeProvider;@CreatedDate 在 MySQL 列精度(datetime 与 datetime(6))上的截断;Spring Data Envers 的历史审计;软删除与审计的配合
    京ICP备2026067502号-1京公网安备11010502063487号