Hibernate 6将Instant存储为UTC而非EST问题求助
解决Hibernate 6.4.1将Instant以EST时区存储到PostgreSQL的timestamp without time zone列的问题
问题背景
将Spring Boot应用从Hibernate 5升级到6.4.1.Final后,尽管JVM和数据库配置为EST时区,使用Instant类型的实体字段存储到PostgreSQL的timestamp without time zone列时,仍以UTC时间存储,而非升级前的EST本地时间。
当前配置信息:
- 数据库列类型:
timestamp without time zone - 实体字段类型:
Instant - 已尝试但未生效的配置:
hibernate.timezone.default_storage: NORMALIZE hibernate.jdbc.time_zone: America/New_York
解决方案
1. 修正Spring Boot中Hibernate属性的配置前缀与存储策略
在Spring Boot中,Hibernate的配置属性必须通过spring.jpa.properties.*前缀传递,直接使用hibernate.*不会被框架正确加载。同时将存储策略调整为STORAGE_TIMEZONE(该策略会把时间转换为存储时区的本地时间,而非归一化到UTC):
spring.jpa.properties.hibernate.jdbc.time_zone=America/New_York spring.jpa.properties.hibernate.timezone.default_storage=STORAGE_TIMEZONE
2. 为实体字段显式指定时区
在@Column注解中添加timezone属性,强制该字段使用指定时区完成存储转换:
@Entity public class AppConfig { public AppConfig() { this.setCreatedDate(Instant.now()); } @Column(name = "created_date", nullable = false, timezone = "America/New_York") private Instant createdDate; // 此处补充getter、setter方法 }
3. 强制Instant映射到TIMESTAMP类型(可选)
Hibernate 6默认将Instant映射到TIMESTAMP WITH TIME ZONE,可通过配置强制映射到TIMESTAMP WITHOUT TIME ZONE,避免类型不匹配引发的时区处理异常:
spring.jpa.properties.hibernate.type.preferred_instant_jdbc_type=TIMESTAMP
验证
配置完成后重新测试存储逻辑:当调用Instant.now()获取UTC时间2024-10-03T19:30:00Z时,数据库中将存储EST时间2024-10-03 14:30:00,与升级前Hibernate 5的行为一致。
内容的提问来源于stack exchange,提问作者Apoorva Manjunath
相关产品推荐
相关产品推荐

