java.sql.Date v.s. java.sql.Timestamp in Oracle 9i

我們都知道 JDBC 中 java.sql.Date 與 java.sql.Timestamp 的差異在於java.sql.Date 是不包含時間的部分

而最近在工作上碰到一個問題…
程式使用

Oracle 9i JDBC thin driver
Jakarta commons DBCP
Jakarta commons DBUtils

等元件進行資料庫的存取..
而使用的資料庫版本為 Oracle9i Enterprise Edition Release 9.2.0.7.0 – 64bit Production

如果撈取 Oracle 資料型態為 DATE 的欄位時,我希望撈出例如 2007/01/24 13:14: 20格式的資料(用 sqlplus 撈出來是有 時間 部分的)
但抓到的資料卻只有 2007/01/24 ,也就是說 時間 的部分不見了

查了很久的問題,加上股溝大神的協助,終於發現原因…
可以參考這個網址

http://www.oracle.com/technology/tech/java/sqlj_jdbc/htdocs/jdbc_faq.htm#08_01

What is going on with DATE and TIMESTAMP?

原來 Oracle 在 9.2 版以前,資料庫資料型態只有 DATE (含有日期與時間),
而 JDBC 9.2 版以前的 drvier 查完資料 mapping 回來會是 java.sql.Timestamp,所以查出來的資料會是包含日期與時間的值

但 Oracle 9.2 後,資料庫資料型態除了 DATE ,還新增了 TIMESTAMP 型態
如果 table schema 建立時使用 DATE 型態建立 (雖然是 DATE , 但是實際上日期時間也都會保留在欄位裡, 用 sqlplus 可以驗證)
但 9.2 版以後的 jdbc driver 查完資料 DATE 型態 mapping 回來會是 java.sql.Date, 而不是 java.sql.Timestamp
所以自然程式取出來的時間部分就不見了

除非 table schema 建立時,欄位型態就是 TIMESTAMP,那麼 jdbc driver 就會幫你轉回 java.sql.Timestamp
但這種情形太少了,原有的 table 我們大部分都是用 DATE 去建立欄位的…

在上述網址中提到四個解法中,

1. 建議我們建立 table 時就要使用 TIMESTAMP,這是最標準的作法
但這不可能,因為目前 table 已經建立了
因此以後如要建立新的 Table , 時間欄位型態請記得改用 TIMESTAMP.

2. 與 3 在如果搭配 DBCP 與 DBUtils 元件的情況下,我們也無法介入調整 (因為根本碰不到 JDBC ResultSet)

4. 方式最簡單,定義一個系統變數 -Doracle.jdbc.V8Compatibility=”true” 即可,看來最快也最簡單,但經我測試的結果,撈出來的資料值會是類似下面降子

2007/01/24 00:00: 00

也就是說,雖然時間的部分出現了,但是值還是 00:00:00 ,所以還是沒用

最後我直接把 JDBC Driver downgrade 到 8.1.7 版,雖然使用舊版,但 DATE 型態就會正確的轉回 java.sql.Timestamp

ps. 需注意的是用 8.1.7 的 jdbc driver 來連 Oracle 9i , Oracle 官方說法是必須需上一個 patch 後才不會有問題
雖然我沒上 patch 也是正常…@@

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料