关于Oracle10g驱动date类型没有时分秒问题
2012-07-03 11:21
417 查看
一般的数据库中,DATE字段仅仅表示日期,不包括日期信息,而Oracle数据库中的DATE数据类型是包括日期、时间的,对于不同的Oracle jdbc驱动版本,对于该问题的处理都有些区别。
最近使用 ORACLE 10G,时间字段因需求,设为了DATE类型,发现hibernate用native
SQL 查询,显示不了时分秒,原来是JDBC驱动自动把date映射为 java.sql.date,故截断了时分秒信息,如果你使用9i或者11g 的驱动程序,就没有该问题,但是Oracle10g的JDBC驱动,你会发现没有时分秒 ,在Oracle9.2之后,引入了内置数据类型TIMESTAMP。之所以引入它,是因为内置数据类型DATE的最小单位为秒;DATE的主要问题是它粒度不能足够区别出两个事件哪个先发生。9.2版本后ORACLE在DATE数据类型上扩展出来了TIMESTAMP数据类型,它包括了所有DATE数据类型的年月日时分秒的信息,而且包括了小数秒(纳秒Nanoseconds级的)的信息。如果你想把DATE类型转换成TIMESTAMP类型,就使用CAST函数。 也正是从oracle
9.2开始,内置数据类型DATE和TIMESTAMP在使用9i的JDBC驱动做查询时,DATE被映射为java.sql.Date,TIMESTAMP被映射为java.sql.Timestamp。 从Oracle11开始,其JDBC驱动程序又重新开始回归为将内置类型DATE映射为java.sql.Timestamp(正如9.2之前的那样)。
所以,时分秒精度的丢失与hibernate无关,是oracle jdbc驱动的问题。最好的解决办法就是:换驱动。经测试,将最开始使用的10g的驱动ojdbc14.jar换为11g的驱动ojdbc5.jar后;
引用
Simple Data Types
What is going on with DATE and TIMESTAMP?
This section is on simple data types. :-)
Prior to 9.2, the Oracle JDBC drivers mapped the DATE SQL type to java.sql.Timestamp. This made a certain amount of sense because the Oracle DATE SQL type contains both date and time information as does java.sql.Timestamp. The more obvious mapping to java.sql.Date
was somewhat problematic as java.sql.Date does not include time information. It was also the case that the RDBMS did not support the TIMESTAMP SQL type, so there was no problem with mapping DATE to Timestamp.
In 9.2 TIMESTAMP support was added to the RDBMS. The difference between DATE and TIMESTAMP is that TIMESTAMP includes nanoseconds and DATE does not. So, beginning in 9.2, DATE is mapped to Date and TIMESTAMP is mapped to Timestamp. Unfortunately if you were
relying on DATE values to contain time information, there is a problem.
There are several ways to address this problem in the 9.2 through 10.2 drivers:
Alter your tables to use TIMESTAMP instead of DATE. This is probably rarely possible, but it is the best solution when it is.
Alter your application to use defineColumnType to define the columns as TIMESTAMP rather than DATE. There are problems with this because you really don't want to use defineColumnType unless you have to (see What is defineColumnType and when should I use it?).
Alter you application to use getTimestamp rather than getObject. This is a good solution when possible, however many applications contain generic code that relies on getObject, so it isn't always possible.
Set the V8Compatible connection property. This tells the JDBC drivers to use the old mapping rather than the new one. You can set this flag either as a connection property or a system property. You set the connection property by adding it to the java.util.Properties
object passed to DriverManager.getConnection or to OracleDataSource.setConnectionProperties. You set the system property by including a -D option in your java command line.
java -Doracle.jdbc.V8Compatible="true" MyApp
Oracle JDBC 11.1 fixes this problem. Beginning with this release the driver maps SQL DATE columns to java.sql.Timestamp by default. There is no need to set V8Compatible to get the correct mapping. V8Compatible is strongly deprecated. You should not use it at
all. If you do set it to true it won't hurt anything, but you should stop using it.
Although it was rarely used that way, V8Compatible existed not to fix the DATE to Date issue but to support compatibility with 8i databases. 8i (and older) databases did not support the TIMESTAMP type. Setting V8Compatible not only caused SQL DATE to be mapped
to Timestamp when read from the database, it also caused all Timestamps to be converted to SQL DATE when written to the database. Since 8i is desupported, the 11.1 JDBC drivers do not support this compatibility mode. For this reason V8Compatible is desupported.
As mentioned above, the 11.1 drivers by default convert SQL DATE to Timestamp when reading from the database. This always was the right thing to do and the change in 9i was a mistake. The 11.1 drivers have reverted to the correct behavior. Even if you didn't
set V8Compatible in your application you shouldn't see any difference in behavior in most cases. You may notice a difference if you use getObject to read a DATE column. The result will be a Timestamp rather than a Date. Since Timestamp is a subclass of Date
this generally isn't a problem. Where you might notice a difference is if you relied on the conversion from DATE to Date to truncate the time component or if you do toString on the value. Otherwise the change should be transparent.
If for some reason your app is very sensitive to this change and you simply must have the 9i-10g behavior, there is a connection property you can set. Set mapDateToTimestamp to false and the driver will revert to the default 9i-10g behavior and map DATE to
Date.
配置:
设为 timestamp 类型。
各个驱动包存在的BUG:
引用
Driver Result
with classes12.zip at C:\Oracle\Ora81\jdbc\lib, Oracle JDBC Drivers release 8.1.6 OK, no problem found
with "oracle 8.1.7 driver\classes12.zip", oracle 8.1.7 driver OK, no problem found
with "oracle 10i\classes12.jar", oracle 10i driver ID corrputed. Bug
with "oracle9i driver\classes12.jar", oracle 9i driver ID corrputed. Bug
with "oracle 10i\ojdbc14.jar", oracle 10i driver ID corrputed. Bug
with "oracle9i driver\ojdbc14.jar", oracle 9i driver ID corrputed. Bug
最近使用 ORACLE 10G,时间字段因需求,设为了DATE类型,发现hibernate用native
SQL 查询,显示不了时分秒,原来是JDBC驱动自动把date映射为 java.sql.date,故截断了时分秒信息,如果你使用9i或者11g 的驱动程序,就没有该问题,但是Oracle10g的JDBC驱动,你会发现没有时分秒 ,在Oracle9.2之后,引入了内置数据类型TIMESTAMP。之所以引入它,是因为内置数据类型DATE的最小单位为秒;DATE的主要问题是它粒度不能足够区别出两个事件哪个先发生。9.2版本后ORACLE在DATE数据类型上扩展出来了TIMESTAMP数据类型,它包括了所有DATE数据类型的年月日时分秒的信息,而且包括了小数秒(纳秒Nanoseconds级的)的信息。如果你想把DATE类型转换成TIMESTAMP类型,就使用CAST函数。 也正是从oracle
9.2开始,内置数据类型DATE和TIMESTAMP在使用9i的JDBC驱动做查询时,DATE被映射为java.sql.Date,TIMESTAMP被映射为java.sql.Timestamp。 从Oracle11开始,其JDBC驱动程序又重新开始回归为将内置类型DATE映射为java.sql.Timestamp(正如9.2之前的那样)。
所以,时分秒精度的丢失与hibernate无关,是oracle jdbc驱动的问题。最好的解决办法就是:换驱动。经测试,将最开始使用的10g的驱动ojdbc14.jar换为11g的驱动ojdbc5.jar后;
引用
Simple Data Types
What is going on with DATE and TIMESTAMP?
This section is on simple data types. :-)
Prior to 9.2, the Oracle JDBC drivers mapped the DATE SQL type to java.sql.Timestamp. This made a certain amount of sense because the Oracle DATE SQL type contains both date and time information as does java.sql.Timestamp. The more obvious mapping to java.sql.Date
was somewhat problematic as java.sql.Date does not include time information. It was also the case that the RDBMS did not support the TIMESTAMP SQL type, so there was no problem with mapping DATE to Timestamp.
In 9.2 TIMESTAMP support was added to the RDBMS. The difference between DATE and TIMESTAMP is that TIMESTAMP includes nanoseconds and DATE does not. So, beginning in 9.2, DATE is mapped to Date and TIMESTAMP is mapped to Timestamp. Unfortunately if you were
relying on DATE values to contain time information, there is a problem.
There are several ways to address this problem in the 9.2 through 10.2 drivers:
Alter your tables to use TIMESTAMP instead of DATE. This is probably rarely possible, but it is the best solution when it is.
Alter your application to use defineColumnType to define the columns as TIMESTAMP rather than DATE. There are problems with this because you really don't want to use defineColumnType unless you have to (see What is defineColumnType and when should I use it?).
Alter you application to use getTimestamp rather than getObject. This is a good solution when possible, however many applications contain generic code that relies on getObject, so it isn't always possible.
Set the V8Compatible connection property. This tells the JDBC drivers to use the old mapping rather than the new one. You can set this flag either as a connection property or a system property. You set the connection property by adding it to the java.util.Properties
object passed to DriverManager.getConnection or to OracleDataSource.setConnectionProperties. You set the system property by including a -D option in your java command line.
java -Doracle.jdbc.V8Compatible="true" MyApp
Oracle JDBC 11.1 fixes this problem. Beginning with this release the driver maps SQL DATE columns to java.sql.Timestamp by default. There is no need to set V8Compatible to get the correct mapping. V8Compatible is strongly deprecated. You should not use it at
all. If you do set it to true it won't hurt anything, but you should stop using it.
Although it was rarely used that way, V8Compatible existed not to fix the DATE to Date issue but to support compatibility with 8i databases. 8i (and older) databases did not support the TIMESTAMP type. Setting V8Compatible not only caused SQL DATE to be mapped
to Timestamp when read from the database, it also caused all Timestamps to be converted to SQL DATE when written to the database. Since 8i is desupported, the 11.1 JDBC drivers do not support this compatibility mode. For this reason V8Compatible is desupported.
As mentioned above, the 11.1 drivers by default convert SQL DATE to Timestamp when reading from the database. This always was the right thing to do and the change in 9i was a mistake. The 11.1 drivers have reverted to the correct behavior. Even if you didn't
set V8Compatible in your application you shouldn't see any difference in behavior in most cases. You may notice a difference if you use getObject to read a DATE column. The result will be a Timestamp rather than a Date. Since Timestamp is a subclass of Date
this generally isn't a problem. Where you might notice a difference is if you relied on the conversion from DATE to Date to truncate the time component or if you do toString on the value. Otherwise the change should be transparent.
If for some reason your app is very sensitive to this change and you simply must have the 9i-10g behavior, there is a connection property you can set. Set mapDateToTimestamp to false and the driver will revert to the default 9i-10g behavior and map DATE to
Date.
配置:
<property name="hibernate.connection.oracle.jdbc.V8Compatible">true</property>或者在 数据库中把 date
设为 timestamp 类型。
各个驱动包存在的BUG:
引用
Driver Result
with classes12.zip at C:\Oracle\Ora81\jdbc\lib, Oracle JDBC Drivers release 8.1.6 OK, no problem found
with "oracle 8.1.7 driver\classes12.zip", oracle 8.1.7 driver OK, no problem found
with "oracle 10i\classes12.jar", oracle 10i driver ID corrputed. Bug
with "oracle9i driver\classes12.jar", oracle 9i driver ID corrputed. Bug
with "oracle 10i\ojdbc14.jar", oracle 10i driver ID corrputed. Bug
with "oracle9i driver\ojdbc14.jar", oracle 9i driver ID corrputed. Bug
相关文章推荐
- 插入数据时,保存的date类型时间字段的数据只有年月日,没有时分秒的问题
- Hibernate3.0 数据库存储Date类型没有时分秒问题
- Oracle10g JDBC ojdbc14 DATE类型hibernate查询时分秒问题(纠结困扰了半天,汗)
- Oracle10g JDBC ojdbc14 DATE类型hibernate查询时分秒问题
- Oracle10g JDBC ojdbc14 DATE类型Spring查询时分秒问题
- java spring jdbc Oracle DATE 类型读取时没有时分秒问题及解决方案
- Oracle Date类型字段使用Hibernate插入后没有时分秒的解决
- 关于ADB 没有驱动的问题
- 关于SpringMVC+java+mysql的Date类型的时间问题
- Sqoop 将hdfs上的文件导入到oracle中,关于date类型的问题
- 关于Ubuntu14.04.3安装完成后WI-FI驱动(BCM43142)没有的问题 (续,转)
- hibernate 中使用oracle数据库 与java Date数据类型 只显示到天 不显示时分秒的问题
- OJDBC14导致查询时间时Date类型的时分秒丢失,OJDBC6修正此问题
- 关于Struts 2对Date类型的自动类型转换出错的问题
- 关于Java读取mysql中date类型字段默认值'0000-00-00'的问题
- 关于Java读取mysql中date类型字段默认值'0000-00-00'的问题
- 关于毫秒数转date类型的细节问题
- 关于表单提交时date类型的转换问题
- 关于SpringMVC中String与Date类型转化问题
- 关于Java读取mysql中date类型字段默认值'0000-00-00'的问题