Hibernate执行persist后修改实体@CreationTimestamp创建日期为null原因查询
问题根因
该现象是Hibernate时间戳注解触发逻辑和持久化上下文默认flush机制共同导致的,具体原因如下:
- Hibernate的
@CreationTimestamp注解仅会在实体首次执行INSERT语句的前处理阶段自动赋值,实体后续的更新操作不会修改该字段的值;@UpdateTimestamp注解则会在实体每次执行INSERT/UPDATE语句时自动生成最新时间值。 - 默认配置下,标注了
@Transactional的方法会在事务提交前才统一执行SQL,调用entityManager.persist()仅会将实体加入持久化上下文变为托管状态、生成主键,不会立刻触发INSERT语句。 - 第一种场景中,你在
persist()之后修改了实体的name属性,将实体标记为脏数据。事务提交前Hibernate合并SQL时,会误将该实体判定为待更新的已有实体,跳过@CreationTimestamp的赋值流程,仅触发@UpdateTimestamp的赋值,最终入库时createdDate为null,其余字段正常。 - 新增
entityManager.flush()调用的场景中,flush()会强制将持久化上下文的待执行操作立即同步到数据库,直接触发INSERT语句,正常执行@CreationTimestamp的赋值逻辑,因此创建时间可以正常写入。
可选解决方案
你可以通过以下任意一种方式规避该问题:
- 所有实体属性的赋值/修改操作都放在
persist()调用之前完成,避免persist后修改托管实体的属性 - 在
persist()调用完成后立即手动执行entityManager.flush(),强制触发INSERT语句完成创建时间赋值 - 在实体的
createdDate字段上添加@Column(updatable = false)注解,明确指定该字段不允许更新,强制Hibernate在插入阶段完成该字段的赋值。
内容的提问来源于stack exchange,提问作者notFound
相关产品推荐
相关产品推荐

