完整的信息(它比这里描述的更复杂,可能取决于正在使用的Oracle驱动程序的特定版本)在Richard Yee的答案中 - [现已过期的Nabble链接]
在它从小动作过期之前快速抓取...
罗杰,参见:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
具体来说: 简单数据类型 日期和时间戳是怎么回事?本节介绍简单数据类型。:-)
在 9.2 之前,Oracle JDBC 驱动程序将 DATE SQL 类型映射到 java.sql.Timestamp。这有一定的意义,因为Oracle DATE SQL类型包含日期和时间信息,java.sql.Timestamp也是如此。更明显的java.sql.Date的映射有些问题,因为java.sql.Date不包括时间信息。RDBMS 不支持 TIMESTAMP SQL 类型,因此将 DATE 映射到时间戳也没有问题。
在 9.2 中,对 RDBMS 添加了 TIMESTAMP 支持。日期和时间戳之间的区别在于,时间戳包含纳秒,而日期不包含纳秒。因此,从 9.2 开始,DATE 映射到 Date,TIMESTAMP 映射到 Timestamp。遗憾的是,如果您依赖 DATE 值来包含时间信息,则存在问题。
有几种方法可以解决此问题:
更改表以使用时间戳而不是日期。这可能很少可能,但当它是最好的解决方案时。
更改应用程序以使用 defineColumnType 将列定义为 TIMESTAMP 而不是 DATE。这存在一些问题,因为除非必须,否则您真的不想使用 defineColumnType(请参阅什么是 defineColumnType 以及我什么时候应该使用它?)。
更改应用程序以使用 getTimestamp 而不是 getObject。如果可能的话,这是一个很好的解决方案,但是许多应用程序包含依赖于getObject的通用代码,因此并不总是可能的。
设置 V8 兼容连接属性。这告诉 JDBC 驱动程序使用旧映射而不是新映射。可以将此标志设置为连接属性或系统属性。通过将其添加到传递给 DriverManager.getConnection 或 OracleDataSource.setConnectionProperties 的 java.util.Properties 对象中,可以设置连接属性。您可以通过在 java 命令行中包含 -D 选项来设置系统属性。
java -Doracle.jdbc.V8Compatible=“true” MyApp Oracle JDBC 11.1 修复了这个问题。从此版本开始,默认情况下,驱动程序将 SQL DATE 列映射到 java.sql.Timestamp。无需设置 V8Compatible 即可获得正确的映射。V8Compatible 已被强烈弃用。你根本不应该使用它。如果你把它设置为true,它不会伤害任何东西,但你应该停止使用它。
虽然它很少以这种方式使用,但V8Compatible的存在不是为了修复日期到日期问题,而是为了支持与8i数据库的兼容性。8i(及更早版本)数据库不支持时间戳类型。设置 V8Compatible 不仅导致从数据库读取时 SQL DATE 映射到时间戳,还导致所有时间戳在写入数据库时都转换为 SQL DATE。由于 8i 不受支持,因此 11.1 JDBC 驱动程序不支持此兼容模式。因此,不支持 V8Compatible。
如上所述,默认情况下,11.1 驱动程序在从数据库读取时将 SQL DATE 转换为时间戳。这始终是正确的做法,9i中的更改是一个错误。11.1 驱动程序已恢复到正确的行为。即使您没有在应用程序中设置 V8Compatible,在大多数情况下,您也不应该看到任何行为差异。如果使用 getObject 读取 DATE 列,您可能会注意到差异。结果将是时间戳而不是日期。由于时间戳是 Date 的子类,因此这通常不是问题。您可能会注意到差异的地方是,如果您依靠从 DATE 到 Date 的转换来截断时间分量,或者如果对值执行 toString。否则,更改应该是透明的。
如果由于某种原因,你的应用对此更改非常敏感,并且你只需要具有 9i-10g 行为,则可以设置一个连接属性。将 mapDateToTimestamp 设置为 false,驱动程序将恢复为默认的 9i-10g 行为并将 DATE 映射到 Date。
如果可能,应将列类型更改为时间戳,而不是 DATE。
-理查德
Roger Voss写道:我在stackoverflow上发布了以下问题/问题,所以如果有人知道一个解决方案,很高兴看到它在那里得到解答:
Oracle SQL DATE 转换问题,通过 Java JDBC 使用 iBATIS
以下是问题描述:
我目前正在与使用Java中的iBATIS的Oracle sql DATE转换问题作斗争。
我使用的是 Oracle JDBC 瘦驱动程序 ojdbc14 版本 10.2.0.4.0。iBATIS 版本 2.3.2.Java 1.6.0_10-rc2-b32.
问题围绕着以下 SQL 代码段返回的 DATE 类型的列:
选择 * 从表(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) 按 from_date 排序
包过程调用返回一个 ref 游标,该游标被包装在 TABLE 中,以便于读取结果集,就好像是对表的选择查询一样。
在 PL/SQL Developer 中,返回的 SQL DATE 类型的FROM_DATE列之一对一天中的时间具有精确度:
Tue Dec 16 23:59:00 PST 2008
但是,当我通过iBATIS和JDBC访问它时,该值仅保留到今天的精度:
Tue Dec 16 12:00:00 AM PST 2008
当像这样显示时,这更清晰:
应该是: 自纪元以来1229500740000 毫秒 星期二, 十二月 16, 2008 11:59:00 PM PST
但得到这个相反:自纪元以来1229414400000毫秒 星期二, 十二月 16, 2008 12:00:00 AM PST (作为类 java.sql.Date 的实例)
无论我尝试什么,我都无法公开此 DATE 列的全部精度,以便通过 Java JDBC 和 iBATIS 返回。
iBATIS的映射是这样的:
FROM_DATE : 2008-12-03 : 类 java.sql.日期
当前的 iBATIS 映射是这样的:
我也试过:
或
但是,所有尝试的映射都会生成相同的截断日期值。就好像JDBC在iBATIS接触它之前就已经造成了数据精度损失的损害。
显然,通过JDBC和iBATIS,我失去了一些数据精度,当我留在PL / SQL Developer中运行与测试脚本相同的SQL片段时,这种情况不会发生。完全不可接受,非常令人沮丧,最终非常可怕。