完整信息(它比此处描述的更复杂,可能取决于正在使用的特定版本的 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 TIMESTAMP 支持被添加到 RDBMS。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 转换为 Timestamp。这始终是正确的做法,而 9i 的更改是一个错误。11.1 驱动程序已恢复为正确行为。即使您没有在应用程序中设置 V8Compatible,在大多数情况下,您也不应该看到任何行为差异。如果您使用 getObject 读取 DATE 列,您可能会注意到不同之处。结果将是时间戳而不是日期。由于 Timestamp 是 Date 的子类,这通常不是问题。您可能会注意到不同之处在于您是否依赖从 DATE 到 Date 的转换来截断时间组件,或者您是否对值执行 toString。否则更改应该是透明的。
如果由于某种原因您的应用程序对这种更改非常敏感并且您必须具有 9i-10g 行为,那么您可以设置一个连接属性。将 mapDateToTimestamp 设置为 false,驱动程序将恢复为默认的 9i-10g 行为并将 DATE 映射到 Date。
如果可能,您应该将列类型更改为 TIMESTAMP 而不是 DATE。
-理查德
Roger Voss 写道: 我在 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 片段返回的 DATE 类型的列:
SELECT * 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 以来(作为 java.sql.Date 类的实例)
无论我尝试什么,我都无法公开要通过 Java JDBC 和 iBATIS 返回的此 DATE 列的完整精度。
iBATIS 的映射是这样的:
FROM_DATE:2008-12-03:类 java.sql.Date
当前的 iBATIS 映射是这样的:
我也试过:
或者
但是所有尝试的映射都会产生相同的截断日期值。就好像 JDBC 在 iBATIS 接触它之前就已经造成了丢失数据精度的损害。
显然,当我在 PL/SQL Developer 中运行与测试脚本相同的 SQL 片段时,我会通过 JDBC 和 iBATIS 失去一些数据精度。完全不能接受,非常令人沮丧,最终非常可怕。