使用Hibernate更新时如何获取@CreationTimestamp字段值?
更新时无需额外请求获取@CreationTimestamp字段值的方案
针对你遇到的问题,答案是可以做到,无需额外查询,核心在于正确配置实体类并利用Spring Data JPA的merge逻辑:
问题根源
你更新时返回的created字段为null,大概率是实体配置缺失或merge逻辑未生效导致的:
- 若
created字段未标注@Column(updatable = false),传入的null值会在merge时覆盖数据库原有值(但@CreationTimestamp仅在插入时生效,更新时不会自动生成值,这会导致数据库中created字段被置空) - 若使用
@DynamicUpdate且未保留created字段,merge后返回的实体会保持传入时的null值
正确配置与解决方案
1. 修正实体类配置
给created字段添加@Column(updatable = false),禁止JPA更新该字段,同时确保审计监听器生效:
@Entity @EntityListeners(AuditingEntityListener.class) public class YourEntity { @Id private Long id; @CreationTimestamp @Column(updatable = false) // 关键:阻止更新该字段,保留数据库原有值 private Timestamp created; @UpdateTimestamp private Timestamp updated; // getter、setter 略 }
2. 利用save()的merge逻辑
当你传入带有有效id的未被EntityManager管理的实体(比如前端DTO转换的实体)时,CrudRepository.save()会自动执行merge操作:
- 根据id查询数据库中的完整实体
- 将你传入的实体的非null属性覆盖到查询结果上
- 保存并返回合并后的实体
此时返回的实体中会包含数据库中已有的created字段值,无需额外发起查询请求。
特殊场景备选方案
如果因性能需求需使用自定义更新语句(而非merge),可以通过自定义Repository方法实现更新+查询,但这种方式会产生额外请求,仅作为备选:
public interface YourRepository extends CrudRepository<YourEntity, Long> { @Modifying(flushAutomatically = true, clearAutomatically = true) @Query("UPDATE YourEntity e SET e.updated = CURRENT_TIMESTAMP WHERE e.id = :id") void updateById(@Param("id") Long id); default YourEntity updateAndGet(Long id) { updateById(id); return findById(id).orElseThrow(() -> new RuntimeException("实体不存在")); } }
内容的提问来源于stack exchange,提问作者IgorZ
相关产品推荐
相关产品推荐

