Jooq 本地日期时间字段使用系统时区而不是会话时区



我正在使用jooq(v3.11.9(来访问以UTC时间运行的MySQL数据库。我使用了生成的实体,并且正在使用 JSR-310 时间类型。我在配置中使用的选项:

<javaTimeTypes>true</javaTimeTypes>

我的理解是,MySQLdatetimetimestamp类型都映射到LocalDateTime这是有道理的,因为 MySQL 不会将时区信息与时间一起存储。但是,当我在不同的时区(在我的例子中是 EST(的计算机上运行查询时,即使会话时区是 UTC,日期也都在我的本地计算机时区中。

我已确认会话时区为 UTC

dslContext.fetch("SELECT @@system_time_zone,  @@global.time_zone, @@session.time_zone;")

返回

|@@system_time_zone|@@global.time_zone|@@session.time_zone|
+------------------+------------------+-------------------+
|UTC               |SYSTEM            |SYSTEM             |
+------------------+------------------+-------------------+

时区转换示例:

dslContext.select(MY_TABLE.EPOCH_DT_TM, MY_TABLE.CREATION_TIMESTAMP).from(MY_TABLE).limit(1).fetch()
+-----------------------+-----------------------+
|epoch_dt_tm            |creation_timestamp     |
+-----------------------+-----------------------+
|2019-04-18T13:57:39.163|2019-09-24T16:06:47.754|
+-----------------------+-----------------------+
// CAST to STRING PROPERLY USES SESSION TIMEZONE 
dslContext.select(MY_TABLE.EPOCH_DT_TM.cast(org.jooq.impl.SQLDataType.VARCHAR(100)), MY_TABLE.CREATION_TIMESTAMP.cast(org.jooq.impl.SQLDataType.VARCHAR(100))).from(MY_TABLE).limit(1).fetch()
+--------------------------+--------------------------+
|cast                      |cast                      |
+--------------------------+--------------------------+
|2019-04-18 17:57:39.163000|2019-09-24 20:06:47.754000|
+--------------------------+--------------------------+

我生成的实体中的字段:

public final TableField<MyTableRecord, LocalDateTime> EPOCH_DT_TM = createField("epoch_dt_tm", org.jooq.impl.SQLDataType.LOCALDATETIME, this, "");
public final TableField<MyTableRecord, LocalDateTime> CREATION_TIMESTAMP = createField("creation_timestamp", org.jooq.impl.SQLDataType.LOCALDATETIME.nullable(false).defaultValue(org.jooq.impl.DSL.field("CURRENT_TIMESTAMP(6)", org.jooq.impl.SQLDataType.LOCALDATETIME)), this, "");

所以我的问题是:

  1. 这是预期行为吗?记录不应该在表中填充原始(非时区(日期。由于某种原因,日期是否仍在引擎盖下转换为java.sql.Timestamp?

  2. 如果这是预期行为,是否有任何方法可以确保获取会话时区中的日期,而不考虑客户端计算机上的本地时区?如果代码的行为取决于计算机时区,则很难在本地进行测试。

提前感谢您的帮助。

我最近发现,根据所使用的数据库驱动程序,jOOQ 可能会在 DateTime 解析中表现出一些奇怪的行为。 jOOQ 将偏移日期时间返回为 Z (UTC(,即使它不是

具体来说,在我的情况下,使用不同的 Postgres 驱动程序会导致 DefaultBinding.java接收具有时间戳的日历对象,但对其调用 toString 以进行解析。 事实证明,toString没有打印时区,然后jOOQ推断它是本地时间。

对我来说,DefaultBinding.java(我使用的是时区时间戳(中的违规行是:

else if (type == OffsetDateTime.class) {
result = (T) offsetDateTime(ctx.resultSet().getString(ctx.index()));
}

您可能在该系列的其他 if 中处于不同的行,基于没有时区。

在我的测试中,我还发现更改系统时间会更改结果,但更改会话时间没有任何作用。

对我来说幸运的是,切换到标准 Postgres 驱动程序解决了这个问题。 如果没有,我将研究重载 OffsetDateTime 的绑定,以修复 toString 的使用及其相关时区的剥离。 不幸的是,您可能需要遵循该路径,除非您也使用可以升级或替换的 SQL 驱动程序。 或者,您可以使用时区存储它,然后在从数据库加载时转换为所需的时区。

相关内容

  • 没有找到相关文章

最新更新