通过Java JDBC使用iBATIS的Oracle SQL DATE转换问题

通过Java JDBC使用iBATIS的Oracle SQL DATE转换问题,第1张

通过Java JDBC使用iBATIS的Oracle SQL DATE转换问题

完整的信息(而且比这里描述的要复杂得多,并且可能取决于所使用的Oracle驱动程序的特定版本)在Richard
Yee的答案中-[现在过期到Nabble的链接]


从小点心过期之前快速抢…

罗杰(Roger),请参阅: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的java.util.Properties对象或OracleDataSource.setConnectionProperties中来设置连接属性。您可以通过在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,而且还导致将所有Timestamps写入数据库时​​均转换为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。

如果可能,应将列类型更改为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(?,?,?,?,?,?,?,?,?,?

包过程调用返回一个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毫秒,太平洋标准时间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映射是这样的:

我也尝试过:

要么

但是所有尝试的映射都会产生相同的截断的Date值。好像JDBC在iBATIS甚至没有达到它之前就已经失去了丢失数据精度的损害。

显然,我通过JDBC和iBATIS失去了一些数据精度,而当我留在PL / SQL
Developer中运行与测试脚本相同的SQL代码段时,这并没有发生。完全不能接受,非常令人沮丧,最终非常可怕。



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5615976.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存