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;
问题原因
@Audited注解的干扰
你的实体使用了Hibernate Envers的@Audited注解实现审计功能,而其他正常的表大概率没有这个注解。当@Audited与未指定@Temporal的@CreationTimestamp+java.util.Date组合使用时,Envers在生成审计表和处理字段类型映射时出现了类型推断偏差——它没有正确将java.util.Date映射为SQL的TIMESTAMP类型,导致时间值的生成或存储逻辑出错,最终写入了错误的旧日期。@CreationTimestamp与@UpdateTimestamp的行为差异@CreationTimestamp仅在实体首次插入时生成一次时间戳,一旦类型映射出错,错误值会被直接写入数据库且不会被覆盖;@UpdateTimestamp会在实体每次更新时重新生成当前时间戳,即使存在短暂的类型映射问题,新生成的正确时间会覆盖错误值,因此表现正常。
无
@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

