You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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操作:

  1. 根据id查询数据库中的完整实体
  2. 将你传入的实体的非null属性覆盖到查询结果上
  3. 保存并返回合并后的实体

此时返回的实体中会包含数据库中已有的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:12:44