【问题标题】:Changed behaviour of java.sql.Date after OJBC client upgradeOJBC 客户端升级后 java.sql.Date 的行为改变
【发布时间】:2014-10-16 12:15:13
【问题描述】:

在将 OJDBC 客户端从版本 11.2.0 升级到 12.1.0 后,我在将 java.sql.Date 对象绑定到 PreparedStatement 时遇到了不同的行为。

在准备好的语句中,一个宿主变量“f.plan_date = ?”应该与 java.util.Date 对象的值绑定,作为在代码中其他地方获得的输入。 Oracle 表中的列数据类型是“DATE”,只应考虑日期部分——时间无关紧要。

我通过以下方式在 java.sql.Date 对象中翻译了 java.util.Date 对象: statementRegisterJobs.setDate(3, new java.sql.Date(planDate.getTime()));

这适用于 11.2.0 客户端。但是,升级到 12.1.0 后,事情往往会出错。不再检索任何记录。经过数小时的调试,我发现问题与日期变量有关。以下工作方式将我的记录归还给我: statementRegisterJobs.setDate(3, java.sql.Date.valueOf("2014-08-21"));

有人可以澄清这种行为吗? java.util.Date 对象最终可以有一个时间组件,我有一种不确定的感觉,这可能与问题有关。另一方面,以下项目应该证明在 java.sql.Date 中忽略了时间组件,无论对象是如何构造的......

  • 在 java.sql.Date 的 Java 6 API 中,我发现以下语句:“此方法已弃用,不应使用,因为 SQL 日期值没有时间组件。” (方法'getHours()')。所以这意味着在将 java.util.Date 转换为 java.sql.Date 时忽略了时间方面。
  • 构造函数文档中的信息证实了这一点:“使用给定的毫秒时间值构造 Date 对象。如果给定的毫秒值包含时间信息,驱动程序会将时间组件设置为默认时区的时间(运行应用程序的 Java 虚拟机的时区)对应于 0 GMT。”
  • 此外,我无法从 java.sql.Date 对象中获取可能的时间方面:toString() 只给我日期,getHours() 抛出异常。
  • 这与 JDBC 客户端中的更新有何关联?

感谢您的任何想法:) 非常感谢您。

【问题讨论】:

  • 只是一些基本的想法:我们也处理日期,但首先实例化一个公历,将所有时间片段设置为 0,并使用 setTimestamp(...) 初始化来自该对象的准备好的语句。完美运行,但数据库不是 ORA 而是 MySql。
  • 参考docs for the constructor 可能更有用,它以迂回的方式表示时间被剥夺了。您是否验证了参数在 Oracle 端的实际时间?是 planDate 时间(如果有的话),还是时区问题?
  • 在数据库中,只存储一个日期,没有时间。我想它可能会默认为 00:00:00。 (如果我使用 Toad 检查字段信息,则会标记“空时间”。)
  • 日期总是有时间的,即使是午夜。我在问数据库将什么视为绑定值。您可以查询 select to_char(?, 'YYYY-MM-DD HH24:MI:SS') from dual 并绑定相同的 planDate 值,然后查看返回的内容,以及与您期望在 planDate 中的内容相比如何?
  • 在定义了以下变量:java.util.Date utilDate = new Date();java.sql.Date sqlDate1 = new java.sql.Date(utilDate.getTime());java.sql.Date sqlDate2 = java.sql.Date.valueOf("2014-08-27"); 并将它们绑定到您提出的语句 (SELECT to_char(?, 'YYYY-MM-DD HH24:MI:SS') testDate FROM dual) 之后,我想我对这个问题有了更多的了解。

标签: java sql oracle date ojdbc


【解决方案1】:

与 Java API 声明的相反,当通过传递毫秒时间值创建 java.sql.Date 对象时,时间方面似乎存储在对象中,并且在使用 12.1.0 OJDBC 驱动程序时不默认为零.

这是我设置的测试:

java.util.Date utilDate = new Date();
java.sql.Date sqlDate1 = new java.sql.Date(utilDate.getTime());
java.sql.Date sqlDate2 = java.sql.Date.valueOf("2014-08-27");

我准备了如下语句(SELECT to_char(?, 'YYYY-MM-DD HH24:MI:SS') testDate FROM dual),同时绑定了sqlDate1和sqlDate2,得到如下结果。

  1. 使用驱动程序版本 11.2.0

    • sqlDate1:​​2014-08-27 00:00:00
    • sqlDate2:2014-08-27 00:00:00
  2. 使用驱动程序版本 12.1.0

    • sqlDate1:​​2014-08-27 14:47:29
    • sqlDate2:2014-08-27 00:00:00

这与 API 中的文档不符:

如果给定的毫秒值包含时间信息,驱动程序 将时间组件设置为默认时区中的时间( 运行应用程序的 Java 虚拟机的时区) 对应于 0 GMT

但是,知道这一点后,我可以通过将 sql 日期对象的时间信息强制为午夜来解决此问题。

【讨论】:

猜你喜欢
  • 2023-02-04
  • 1970-01-01
  • 2018-08-13
  • 2016-03-31
  • 2017-10-18
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 2016-07-27
相关资源
最近更新 更多