使用@CreationTimestamp(source=DB)是否多余?替代方案及兼容问题咨询
问题解答
一、除了生成Schema,用@CreationTimestamp(source = SourceType.DB)替代@Column(updatable = false, insertable = false)的合理理由
- 语义更直观,可读性更强:
@CreationTimestamp(source = SourceType.DB)直接点明这个字段是数据库维护的创建时间戳,其他开发者看代码时一眼就能get到字段的业务意义;而@Column(...)只是从读写权限上做限制,没说清字段的用途,需要结合上下文猜。 - 从根源避免手动赋值坑:虽然
@Column(updatable = false, insertable = false)限制了插入更新时的赋值,但要是代码里不小心通过ORM API手动给这个字段设值,有些框架可能会忽略这个限制,引发不必要的错误。用@CreationTimestamp(source = SourceType.DB)的话,ORM框架会明确知道这个字段由数据库生成,根本不会把它放进INSERT/UPDATE语句里,彻底杜绝这类风险。 - 适配ORM框架的额外特性:像MyBatis-Plus这类框架对
@CreationTimestamp有专门适配,比如查询结果映射时自动处理时间类型转换,批量操作时精准跳过该字段的处理,比单纯用@Column注解更省心,也能提升点执行效率。
二、和@Immutable注解冲突的解决办法
同时用这俩注解出现JpaSystemException: Lock mode not supported,原因是@Immutable标记实体为不可变,ORM框架会用特殊的锁模式或缓存策略处理,但@CreationTimestamp需要插入后从数据库拿生成的时间戳,这和不可变实体的逻辑撞了。
给几个可行的解决思路:
- 去掉
@Immutable,换用@Column(updatable = false):如果业务允许实体创建后还能被ORM处理(比如读取生成的时间戳),就把@Immutable删掉,用@Column(updatable = false)保证创建后字段不会被修改,同时保留@CreationTimestamp(source = SourceType.DB)来获取数据库生成的时间。 - 手动处理创建时间:要是必须保留
@Immutable,就去掉@CreationTimestamp,只保留@Column(updatable = false, insertable = false),插入实体后单独写个查询语句把数据库生成的时间戳查出来,再赋值给实体(注意不可变实体可能得通过构造器或者特殊方法来赋值)。 - 自定义实体监听器:如果用的是Spring Data JPA这类可扩展的框架,可以自己写个实体监听器,在实体插入完成后手动从数据库查时间戳并注入,绕开两个注解的冲突逻辑。
内容的提问来源于stack exchange,提问作者littleAlien
相关产品推荐
相关产品推荐

