完整信息(它比此处描述的更复杂,并且可能取决于正在使用的特定版本的 Oracle 驱动程序)在 Richard Yee 的回答中 - [现在指向 Nabble 的链接已过期]
在 nabble 过期之前快速抓取...
罗杰,
见:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
具体来说:
简单数据类型
DATE 和 TIMESTAMP 发生了什么?
本节介绍简单数据类型。 :-)
在 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映射到Timestamp是没有问题的。
在 9.2 中,向 RDBMS 添加了 TIMESTAMP 支持。 DATE 和 TIMESTAMP 之间的区别在于 TIMESTAMP 包括纳秒,而 DATE 不包括。因此,从 9.2 开始,DATE 映射到 Date 并且 TIMESTAMP 映射到 Timestamp。不幸的是,如果您依赖 DATE 值来包含时间信息,就会出现问题。
有几种方法可以解决这个问题:
更改您的表以使用 TIMESTAMP 而不是 DATE。这可能很少有可能,但它是最好的解决方案。
更改您的应用程序以使用 defineColumnType 将列定义为 TIMESTAMP 而不是 DATE。这样做存在问题,因为除非必须,否则您真的不想使用 defineColumnType(请参阅什么是 defineColumnType 以及何时应该使用它?)。
更改您的应用程序以使用 getTimestamp 而不是 getObject。如果可能,这是一个很好的解决方案,但是许多应用程序包含依赖于 getObject 的通用代码,因此并不总是可行。
设置 V8Compatible 连接属性。这告诉 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 的存在不是为了修复 DATE to Date 问题,而是为了支持与 8i 数据库的兼容性。 8i(和更早版本)数据库不支持 TIMESTAMP 类型。设置 V8Compatible 不仅会导致 SQL DATE 在从数据库读取时映射到 Timestamp,还会导致所有 Timestamp 在写入数据库时都转换为 SQL DATE。由于不支持 8i,因此 11.1 JDBC 驱动程序不支持此兼容模式。因此,不支持 V8Compatible。
如上所述,11.1 驱动程序在读取数据库时默认将 SQL DATE 转换为时间戳。这始终是正确的做法,而 9i 的更改是一个错误。 11.1 驱动程序已恢复为正确行为。即使您没有在应用程序中设置 V8Compatible,在大多数情况下,您也不应该看到任何行为差异。如果您使用 getObject 读取 DATE 列,您可能会注意到不同之处。结果将是时间戳而不是日期。由于 Timestamp 是 Date 的子类,这通常不是问题。您可能会注意到不同之处在于您是否依赖从 DATE 到 Date 的转换来截断时间组件,或者您是否对值执行 toString。否则更改应该是透明的。
如果由于某种原因您的应用程序对这种更改非常敏感,并且您必须具有 9i-10g 行为,那么您可以设置一个连接属性。将 mapDateToTimestamp 设置为 false,驱动程序将恢复到默认的 9i-10g 行为并将 DATE 映射到 Date。
如果可能,您应该将列类型更改为 TIMESTAMP 而不是 DATE。
-理查德
罗杰·沃斯写道:
我在stackoverflow上发布了以下问题/问题,所以如果有人知道解决方案,很高兴看到它在那里得到解答:
通过 Java JDBC 使用 iBATIS 的 Oracle SQL DATE 转换问题
问题描述如下:
我目前正在努力解决使用来自 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 的 sn-p 返回的 DATE 类型的列:
选择 *
FROM TABLE(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) 由 from_date 订购
包过程调用返回一个引用游标,该游标被包装在一个 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 毫秒
太平洋标准时间 2008 年 12 月 16 日星期二晚上 11:59:00
但是得到这个:
自纪元以来的 1229414400000 毫秒
太平洋标准时间 2008 年 12 月 16 日,星期二 12:00:00 AM
(作为类 java.sql.Date 的实例)
无论我尝试什么,我都无法公开要通过 Java JDBC 和 iBATIS 返回的此 DATE 列的完整精度。
iBATIS 的映射是这样的:
FROM_DATE : 2008-12-03 : java.sql.Date 类
当前的 iBATIS 映射是这样的:
我也试过了:
或
但所有尝试的映射都会产生相同的截断日期值。就好像 JDBC 在 iBATIS 接触它之前就已经造成了丢失数据精度的损害。
很明显,当我在 PL/SQL Developer 中运行与测试脚本相同的 SQL sn-p 时,我通过 JDBC 和 iBATIS 会丢失一些数据精度。完全不能接受,非常令人沮丧,最终非常可怕。