【问题标题】:Using ZonedDateTime with datetimeoffset in SQLServer在 SQLServer 中使用 ZonedDateTime 和 datetimeoffset
【发布时间】:2023-03-04 11:51:01
【问题描述】:

我有一个使用带有 datetimeoffset 列的 SQLServer 数据库的应用程序。最好使用 ZonedDateTime 作为我的 JPA 实体对象类型,如下所示:

@Column(name = "CreateTimestamp", nullable = false)
ZonedDateTime createTimestamp;

但是,时区未正确保存。无论我在 ZonedDateTime 中将 ZoneId 设置为什么,数据库中的值都将始终为 GMT 格式。

看看Microsoft's JDBC mapping diagram,推荐使用的类是microsoft.sql.DateTimeOffset,这不是我想要的。

我已经探索过使用@Converter 在两者之间进行映射,但是必须提供这样的特殊知识似乎是一个危险信号,表明我做错了 - 特别是因为我需要它在集成测试中工作使用 H2。

以与供应商无关的方式使用 datetimeoffset 和 ZonedDateTime 的最佳方式是什么?

【问题讨论】:

    标签: java sql-server jpa


    【解决方案1】:

    我不想回答自己的问题,但我想确保解决方案已记录在案。

    解决方案是使用@Converter 将 ZonedDateTime 转换为字符串。 Hibernate 会将其作为 VARCHAR 传递给 SQLServer,并且数据库本身会将值隐式转换为 datetimeoffset - 与执行独立查询时转换硬编码日期的方式相同。

    以下转换器适用于我的情况:

    @Converter(autoApply = true)
    public class ZonedDateTimeConverter implements AttributeConverter<ZonedDateTime, String>
    {
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSSS xxx";
    
        @Override
        public String convertToDatabaseColumn(ZonedDateTime zonedDateTime)
        {
            return DateTimeFormatter.ofPattern(DATE_FORMAT).format(zonedDateTime);
        }
    
        @Override
        public ZonedDateTime convertToEntityAttribute(String dateAsString)
        {
            return ZonedDateTime.parse(dateAsString, DateTimeFormatter.ofPattern(DATE_FORMAT));
        }
    }
    

    此外,这也适用于 H2,因此它可以在集成测试中使用,而无需执行任何供应商特定的逻辑。

    【讨论】:

    • 问题是你使用的是哪个版本的Hibernate?最近的版本确实“支持”ZonedDateTime(即使 jdbc 4.2 规范不支持),但是有一些问题,比如您可能想将hibernate.jdbc.time_zone 设置为数据库服务器运行的时区。此外,您提到的 Microsoft JDBC 映射图也不再是最新的:从 7.1.4 版开始,mssql-jdbc 驱动程序还支持 Java 的OffsetDateTime(而不是使用microsoft.sql.DateTimeOffset):github.com/microsoft/mssql-jdbc/pull/830
    【解决方案2】:

    这里有点问题。 数据时间 ZoneDateTime 包含比 OffsetDateTime 更多的信息。 区。 请注意,区域与偏移量不同。它更多。 在给定时刻,两个区域可能具有相同的偏移量,但几个月后,一个区域“向前弹起”,另一个区域没有。 或者,它们在不同的日子向前涌现。 在将字符串从 OffsetDateTime 转换为 ZoneDateTime 时,您将引入一个以前不存在的区域。

    【讨论】:

    • 是的,这就是为什么 DatetimeOffset 有点没用。我真正想要的是区域。
    猜你喜欢
    • 2014-06-29
    • 2016-06-18
    • 2019-09-24
    • 1970-01-01
    • 2019-03-12
    • 2018-08-16
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多