大家好,我是小米,一个写代码也写故事的31岁程序员。
上周五晚上,我在工位上加班修 Bug,手里那杯咖啡都凉透了。原因嘛——老板的一句话:“小米,你这表记录谁创建的、什么时候改的,怎么都没写?”我一脸懵:“啊?这不是数据库自带的吗?”老板笑了笑,“你去查查 JPA Audit。”
就这样,我打开电脑,走上了一条“审计字段自动填充”的觉醒之路。
那些年我们手动维护的时间戳
还记得刚入行那会儿,我写的每个实体类都像这样:
每次插入数据,我要在 Service 里手动加:
每次修改,又要写:
那时候觉得很自然,但后来项目一多,几十个表、几百个接口,这种重复代码简直要命。更惨的是——忘了写!测试一改表数据,时间没更新,历史数据都乱套。于是我暗暗发誓:“有朝一日,一定要让这些字段自动更新!”
直到那天,JPA 的 @CreatedDate 和 @LastModifiedDate 出现在我的视野中,像是照进加班狗世界的一束光。
JPA Audit:让时间自动生长的魔法
Spring Data JPA 提供了一个非常优雅的方案:Auditing(审计)机制。简单来说,就是自动帮你记录实体的创建时间、修改时间、创建人、修改人。
其中,最常用的两个注解就是:
- @CreatedDate —— 自动记录创建时间。
- @LastModifiedDate —— 自动记录最后修改时间。
是不是一看名字就懂了?没错,真正的懒人神器。
动手开整:三步启用审计魔法
第一步:在配置类上开启审计功能
在任意一个配置类或启动类上加上这行注解:
@EnableJpaAuditing
这句话的意思很简单:告诉 Spring,“以后帮我盯着数据库记录的变化,谁新建、谁修改都记下来!”
第二步:在实体类上声明审计监听
在你的实体类上加个监听器,让 Spring 知道要“监听”它的变化。
@EntityListeners(AuditingEntityListener.class)
这一步很关键,没有它,Spring 不知道你要被审计。
第三步:加上注解就完事了
然后呢?没了。真的没了!你再执行一次插入或更新,时间就会自动写入数据库,不用再管!
原理浅析:Spring 到底干了啥?
有些同学可能会好奇:“小米,它到底是怎么知道我在新增还是修改呢?”
其实,Auditing 的底层机制是基于 实体监听器(Entity Listener) 的。
当你在实体上加上 @EntityListeners(AuditingEntityListener.class) 时,Spring 会在执行 save() 前后拦截生命周期事件(比如 @PrePersist、@PreUpdate),在插入前自动设置 @CreatedDate 字段,在更新前自动更新 @LastModifiedDate 字段。
这就像数据库触发器一样,但实现更轻量、更优雅,还能配合 @CreatedBy、@LastModifiedBy 记录操作人。
实战演练:一个例子走天下
我当时在项目里这样写的:
然后我在启动类上加上:
当我执行:
数据库里自动生成了时间戳!
过几分钟,我再修改这个用户名字,再执行一次 save,发现 update_time 自动变成最新的时间,而 create_time 完好无损。那一刻我真心感叹:Spring Data JPA 太懂程序员了!
顺便说下时间精度的小坑
很多人第一次用时会踩一个坑:数据库时间没自动更新。
别慌,常见原因就两个:
- 没加 @EnableJpaAuditing: 这是整个机制的总开关,不加它所有注解都白搭。
- 字段类型不对: 推荐用 LocalDateTime,如果你用 Date 或 Instant,要确保配置了合适的转换器。
另外,@Column(updatable = false) 千万别乱加在 @LastModifiedDate 上,否则它更新不了!
进阶玩法:记录创建人和修改人
除了时间,JPA 还能帮你自动记录“谁”创建了这条数据。
新增两个注解即可:
- @CreatedBy
- @LastModifiedBy
比如:
但要注意:这两个字段依赖于 AuditorAware 接口,你需要自己告诉 JPA 当前是谁在操作:
在真实项目中,你可以从登录上下文中取当前用户名。这样,每次插入或更新数据,createUser 和 updateUser 就会自动带上值。
再说点小故事
我把这套审计机制加到项目后,老板第一次审查代码时问:“你这次写的日志表不错啊,时间记录得很清楚。”
我笑着回:“我没写,Spring 帮我写的。”
他愣了两秒,然后竖起大拇指:“干得漂亮。”
从那以后,我再也不用担心忘记更新时间、创建时间。甚至在代码评审时,同事看到注解风格的审计方案,都感叹一句:“这才是优雅的后端。”
总结:三行注解,让代码更干净
用一句话总结今天的主角:
@CreatedDate 和 @LastModifiedDate,不仅让你少写代码,还能让系统更可靠、更可追溯。
它们背后体现的是“让框架帮你做重复的事,让开发者专注在业务逻辑”的理念。
所以,下一次当你新建实体类时,不妨给它加上这些注解。让时间自动生长,让代码更有生命力。
END
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
我们下次见~