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

Hibernate @CreationTimestamp在PostgreSQL中存储日期异常求助

问题分析与解答

问题背景

在Spring Boot项目中使用Hibernate的@CreationTimestamp(导入路径:import org.hibernate.annotations.CreationTimestamp;)标记java.util.Date类型的private Date createdDate字段(无setter方法),用于自动存储创建时间戳。在PostgreSQL 9.5.4环境下,保存数据时createdDate被错误存储为旧日期(2022-10-28),实际应为2023-01-23;但@UpdateTimestamp标记的updatedDate工作正常。添加@Temporal(TemporalType.TIMESTAMP)注解后,createdDate存储恢复正常,但同一数据库架构下未使用该注解的其他表仍能正常存储日期。

实体代码(简化):

@Entity
@Audited
public class EntityClassName implements Serializable{
    private static final long serialVersionUID = 6004021640401026397L;
    
    private String createdBy;
    
    @CreationTimestamp
    private Date createdDate;
    
    private String updatedBy;
    
    @UpdateTimestamp
    private Date updatedDate;
}

修复后代码:

@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;

问题原因

  1. @Audited注解的干扰
    你的实体使用了Hibernate Envers的@Audited注解实现审计功能,而其他正常的表大概率没有这个注解。当@Audited与未指定@Temporal的@CreationTimestamp+java.util.Date组合使用时,Envers在生成审计表和处理字段类型映射时出现了类型推断偏差——它没有正确将java.util.Date映射为SQL的TIMESTAMP类型,导致时间值的生成或存储逻辑出错,最终写入了错误的旧日期。

  2. @CreationTimestamp与@UpdateTimestamp的行为差异

    • @CreationTimestamp仅在实体首次插入时生成一次时间戳,一旦类型映射出错,错误值会被直接写入数据库且不会被覆盖;
    • @UpdateTimestamp会在实体每次更新时重新生成当前时间戳,即使存在短暂的类型映射问题,新生成的正确时间会覆盖错误值,因此表现正常。
  3. 无@Audited表的正常逻辑
    对于未使用@Audited的表,Hibernate的基础ORM处理逻辑可以正确推断java.util.Date+@CreationTimestamp的字段类型应为TIMESTAMP,无需额外的@Temporal注解就能正常工作。

总结

当使用Hibernate Envers的@Audited注解时,必须为java.util.Date类型的@CreationTimestamp字段显式指定@Temporal(TemporalType.TIMESTAMP),确保Envers的审计逻辑能正确识别字段的时间类型,避免时间存储错误。

内容的提问来源于stack exchange,提问作者Rohit Patnaik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:45:34