我正在将 Spring Boot 2 + Hibernate 5 应用程序升级到 Spring Boot 3 和 Hibernate 6。更新时,我注意到 Hibernate 6 处理 java Instant 字段到没有时区信息的表列之间的转换的方式与 Hibernate 5 不同。
在 Hibernate 6 中,当持久化一个实例字段具有值的对象时2023-02-20T04:08:00Z
,该值被映射到2023-02-20T05:08:00Z
检索后。正如所解释的here https://thorben-janssen.com/hibernate-6-offsetdatetime-and-zoneddatetime/这可能与映射“即时”和“持续时间”字段的新方式有关。
我设法通过添加来解决这个问题@JdbcType(InstantAsTimestampJdbcType.class)
给每个Instant
领域中的每一个@Entity
应用程序中的类。但是,我宁愿对此事进行单一的集中配置,而不是向应用程序中的每个 Instant 字段添加注释。我尝试了几种方法:
选项 1:添加属性hibernate.timezone.default_storage
并尝试了所有存储类型选项(source https://thorben-janssen.com/hibernate-6-offsetdatetime-and-zoneddatetime/#5_different_TimezoneStorageTypes):
spring.jpa.properties.hibernate.timezone.default_storage=NORMALIZE_UTC
选项 2:声明 HibernatePropertiesCustomizer bean:
@Bean
public HibernatePropertiesCustomizer hibernatePropertiesCustomizerPG() {
return hibernateProperties -> {
hibernateProperties.put(EntityManagerFactoryBuilderImpl.TYPE_CONTRIBUTORS,
(TypeContributorList) () -> List.of(
(TypeContributions typeContributions, ServiceRegistry serviceRegistry) ->
typeContributions.contributeJdbcType(InstantAsTimestampJdbcType.INSTANCE)));
};
}
选项 3:创建HibernatePropertiesCustomizer
:
@Configuration
public class HibernateTypeContributorConfiguration implements HibernatePropertiesCustomizer {
@Override
public void customize(Map<String, Object> hibernateProperties) {
hibernateProperties.put(
EntityManagerFactoryBuilderImpl.TYPE_CONTRIBUTORS,
(TypeContributorList) () -> List.of((jdbcType, serviceRegistry) -> jdbcType.contributeJdbcType(InstantAsTimestampJdbcType.INSTANCE))
);
}
}
不幸的是,到目前为止,这些方法都没有奏效。有谁知道如何InstantAsTimestampJdbcType
可以注册吗?或者有更好的方法来解决这个问题吗?
请注意,修改表列以添加时区信息不是一种选择。