gpt4 book ai didi

mysql - 为什么我在使用 JOOQ 时会一次性恢复日期?

转载 作者:行者123 更新时间:2023-11-29 07:22:28 26 4
gpt4 key购买 nike

我们正在使用 jOOQ 与包含此表的 MySQL 数据库对话:

CREATE TABLE daily_sessions
(
session_id INT AUTO_INCREMENT NOT NULL,
user_id VARCHAR(45) NULL,
day date NULL,
CONSTRAINT PK_DAILY_SESSIONS PRIMARY KEY (session_id)
);

我们启用了对 JSR-310 类型的支持,因此我们在 Java/Kotlin 端使用 LocalDate 来映射它。

我们看到的是 day 字段被检索到一天的偏移量。 jOOQ 记录的插入和选择语句似乎表明它在绑定(bind) SQL 参数时做了正确的事情,但是当结果返回时它显示前一天:

2019-04-05 09:32:08 [Gax-20    ] DEBUG o.j.i.DefaultConnectionProvider - setting auto commit      : false
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - Executing query : select `daily_sessions`.`session_id`, `daily_sessions`.`user_id`, `daily_sessions`.`day` from `daily_sessions` where (`daily_sessions`.`user_id` = ? and `daily_sessions`.`day` = ?)
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - -> with bind values : select `daily_sessions`.`session_id`, `daily_sessions`.`user_id`, `daily_sessions`.`day` from `daily_sessions` where (`daily_sessions`.`user_id` = '87a09702-0d6b-485c-895c-986f238e1d30' and `daily_sessions`.`day` = {d '2011-11-11'})
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - Fetched result : +----------+------------------------------------+----------+
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - : |session_id|user_id |day |
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - : +----------+------------------------------------+----------+
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - : | 13|87a09702-0d6b-485c-895c-986f238e1d30|2011-11-10|
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - : +----------+------------------------------------+----------+
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.tools.LoggerListener - Fetched row(s) : 1
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.i.DefaultConnectionProvider - commit
2019-04-05 09:32:08 [Gax-20 ] DEBUG o.j.i.DefaultConnectionProvider - setting auto commit : true
2019-04-05 09:32:08 [Gax-20 ] DEBUG c.z.hikari.pool.PoolBase - HikariPool-1 - Reset (isolation) on connection com.mysql.cj.jdbc.ConnectionImpl@4af95547

请注意选择如何筛选 2011-11-11,但结果表显示 2011-11-10

这是在我的本地机器 (UTC+10) 上运行的测试,针对也在本地运行的标准 mysql Docker 镜像。

尽管使用了 DATE,但我假设我们遇到了一些时区问题,但我无法通过直接调用 JDBC 来重现该问题。我尝试在运行其他测试的相同设置中运行它:

@Test
fun testDateColumn() {
DriverManager.getConnection("jdbc:mysql://localhost:8890/rewards-test", "root", "").use { con ->
con.createStatement().use { stmt ->
stmt.execute("insert into `daily_sessions` (`user_id`, `day`) values ('a20add98-5a93-417f-a771-848757b2b1f8', {d '2011-11-11'})")
}
con.createStatement().use { stmt ->
stmt.executeQuery("select `daily_sessions`.`session_id`, `daily_sessions`.`user_id`, `daily_sessions`.`day` from `daily_sessions` where (`daily_sessions`.`user_id` = 'a20add98-5a93-417f-a771-848757b2b1f8' and `daily_sessions`.`day` = {d '2011-11-11'})").use { rs ->
while (rs.next()) {
println("${rs.getString(3)} - ${rs.getDate(3)}")
}
}
}
}
}

这段代码产生了预期的输出。 SQL 语句是 jOOQ 日志的直接副本。 jOOQ 肯定还有其他我不明白的东西。

我需要以某种方式在 jOOQ 中配置时区吗?还是我还遗漏了什么?

更新

正如 Lukas 在评论中所建议的那样,我尝试更改我的 JDBC 测试以使用准备好的语句:

@Test
fun testDateColumn() {
DriverManager.getConnection("jdbc:mysql://localhost:8890/rewards-test", "root", "").use { con ->
con.prepareStatement("insert into `daily_sessions` (`user_id`, `day`) values (?, ?)").use { ps ->
ps.setString(1, "a20add98-5a93-417f-a771-848757b2b1f8")
ps.setDate(2, Date.valueOf(LocalDate.of(2011, 11, 11)))
ps.execute()
}
con.prepareStatement("select `daily_sessions`.`session_id`, `daily_sessions`.`user_id`, `daily_sessions`.`day` from `daily_sessions` where (`daily_sessions`.`user_id` = ? and `daily_sessions`.`day` = ?)").use { ps ->
ps.setString(1, "a20add98-5a93-417f-a771-848757b2b1f8")
ps.setDate(2, Date.valueOf(LocalDate.of(2011, 11, 11)))
ps.executeQuery().use { rs ->
while (rs.next()) {
println("${rs.getString(3)} - ${rs.getDate(3)}")
}
}
}
}
}

这确实会产生错误的结果,字符串和日期变体的输出都是 2011-11-10。看来 JDBC 中有些东西我不明白。

更新 2

上面的代码可以通过将默认的 java.util.Calendar 实例作为第三个参数传递给 setDate 方法来修复,即将上面的两种情况替换为:

ps.setDate(2, Date.valueOf(LocalDate.of(2011, 11, 11)), Calendar.getInstance())

使用它我们可以看到预期的输出,而没有第三个参数的普通版本则不会。

JavaDoc of the setDate method表示缺少 Calendar 对象将导致使用 VM 的时区,这似乎完全相同 the definition of Calendar.getInstance() specifies ,这似乎表明什么都不应该改变。

最佳答案

原来是a known bug in the MySQL JDBC driver .我的解决方法是恢复到问题出现之前的更旧版本。

关于mysql - 为什么我在使用 JOOQ 时会一次性恢复日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55526942/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com