首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate在Server中不正确地将ZonedDateTime存储为datetimeoffset偏移量

Hibernate在Server中不正确地将ZonedDateTime存储为datetimeoffset偏移量
EN

Stack Overflow用户
提问于 2016-03-05 00:23:04
回答 1查看 5.8K关注 0票数 2

我希望在Server 2008中使用一个日期时间偏移量列,该列同时存储日期和时间以及时区。

数据库中列的DDL定义:

代码语言:javascript
复制
LastUpdatedDateTime datetimeoffset DEFAULT SysDateTimeOffset()

使用Hibernate映射的实体上字段的Java定义:

代码语言:javascript
复制
private ZonedDateTime lastUpdatedDateTime = ZonedDateTime.now();

我使用Hibernate 5.1.0.Final (通过Spring 1.3.2.RELEASE)并包括org.hibernate:hibernate-java8。

观察到的行为(通过使用WinSQL查询数据库):通过SQL语句插入数据将导致存储正确的日期和时间以及正确的时区: 2016-03-03 13:41:17.5358944 -07:00

通过保存Java实体插入数据(按照上面的Java代码片段初始化字段)。Java将日期/时间值(保存前)报告为:2016-03-04T14:18:17.076-07:00America/丹佛

保存后,WinSQL将存储在数据库中的值报告为: 2016-03-04 14:18:17.0760000 +00:00

这有相同的日期和时间,但错误的时区(UTC而不是-07:00)。

当我使用时间戳而不是ZonedDateTime在Java中声明字段时,我得到了相同的行为。

如何正确存储时区?我并不关心它是否存储为UTC或-07:00时区,只要基于时区的时间是正确的。我认为Hibernate将提供对此的支持(在hibernate-java8库中),并且无需编写自定义转换器或自定义用户数据类型。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-08 21:13:03

我终于找到了一个解决办法:

  1. 实体字段使用java.time.OffsetDateTime而不是ZonedDateTime。根据Javadoc类,OffsetDateTime用于数据库持久性。
  2. 恢复到Hibernate 4(由于我遇到的其他问题)。因此,如果您在hibernate-java8 8库中使用Hibernate 5,那么我不知道接下来的步骤是否是必要的。
  3. 将Hibernate转换器从OffsetDateTime添加到String。显然,JDBC默认将driver偏移列视为字符串(而不是Microsoft驱动程序文档中建议的microsoft.sql.DateTimeOffset类)。这个转换器中的逻辑必须处理复杂的问题,即Server只存储7位数的纳秒时间,而OffsetDateTime提供9位数。
  4. 确保转换器包含在Hibernate EntityManager中。

这些步骤的详细情况如下:

DDL列定义不变。

实体字段定义:

代码语言:javascript
复制
private OffsetDateTime lastUpdatedDateTime;

转换器级:

代码语言:javascript
复制
@Converter(autoApply = true)
public class OffsetDateTimeConverter implements AttributeConverter<OffsetDateTime, String> {

    private static DateTimeFormatter FORMATTER_FROM_DB = DateTimeFormatter.ofPattern(
      "yyyy-MM-dd HH:mm:ss.nnnnnnn xxx");
    private static DateTimeFormatter FORMATTER_TO_DB = DateTimeFormatter.ofPattern(
      "yyyy-MM-dd HH:mm:ss.nnnnnnnnn xxx");

    @Override
    public String convertToDatabaseColumn(OffsetDateTime attribute) {
        if (attribute == null) {
            return null;
        }
        return attribute.format(FORMATTER_TO_DB);
    }

    @Override
    public OffsetDateTime convertToEntityAttribute(String dbData) {
        if (dbData == null) {
            return null;
        }
        return OffsetDateTime.parse(dbData, FORMATTER_FROM_DB);
    }
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35808423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档