JDBC中日期時間的處理

Java中用類java.util.Date對日期/時間做了封裝,此類提供了對年、月、日、時、分、秒、毫秒以及時區的控制方法,同時也提供一些工具方法,比如日期/時間的比較,前後判斷等。 
java.util.Date中採用一個long型的數來保存日期/時間,它表示從格林威治時間1970年1月1日00點00分00秒至今的毫秒數。 
JDBC中,在這個類的基礎之上擴展了3個類:java.sql.Date,java.sql.Time,java.sql.Timestamp。 
java.sql.Date表示日期,只包括年月日; 
java.sql.Time表示時間,只包括時分秒; 
java.sql.Timestamp表示時間戳,包括年月日,時分秒,還有毫秒和納秒;值得注意的是它比java.util.Date還多了一個納秒。 

這3個類分別對應數據庫的3種數據類型: 
java.sql.Date 日期(只包括年月日) 
java.sql.Time 時間(只包括時分秒) 
java.sql.Timestamp 日期/時間(包括年月日,時分秒,還有毫秒和納秒) 

有了上面的一些基礎知識,下面介紹一些處理技巧。 


 1.對於數據庫種不同的時間類型,要分別採用與之相對應的Java包裝類來存取; 
日期類型用java.sql.Date,時間類型用java.sql.Time,日期/時間類型用java.sql.Timestamp; 
這裏舉個例子:假設要從oracle中獲取系統時間,需要執行sql:select sysdate from dual,然後在通過ResultSet獲取查詢結果時,一定要調用方法:getTimestamp(),這樣纔可以把年月日時分秒都取出來,調用getDate()只能取出年月日,調用getTime()只能取出時分秒。 
調用getString也可以取出來,但是存在問題,見技巧2。 


 2.儘量不要調用getString()來獲取日期/時間類型的數據; 
調用getString()也可以取出時間類型的數據,JDBC在內部將日期/時間轉換爲字符串;但是這個字符串的格式卻取決於數據庫,用Oracle是一種,用Sybase又是一種,mysql又是一種,如果你想兼容多種數據庫,還是不要用getString()的好。 
另外,採用字符串來保存時間存在一些問題,我在另外一篇帖子中解釋過(見:Java中日期/時間的使用技巧【原創】); 
還有是效率問題,用getString()需要在內部將日期時間轉換爲字符串,涉及字符串處理;但用getTimestamp()只需要做整數的運算和處理;而整數的運算處理一般都比字符串處理效率高。 


 3.如何將JDBC的日期/時間類型轉換爲字符串; 
曾經看到過有人這樣寫: 
java.sql.Timestamp timeStamp = //通過數據庫訪問獲取到該數據 
java.util.Date utilDate = new java.util.Date(timeStamp.getTime()); 
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
String str = sdf.format(utilDate); 

這樣也可以達到最終目的,但是有點問題,java.sql.Timestamp是繼承java.util.Date的,因此format的時候直接傳入timeStamp即可,沒有必要臨時創建一個utilDate。像下面這樣就可以了: 
java.sql.Timestamp timeStamp = //通過數據庫訪問獲取到該數據 
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
String str = sdf.format(timeStamp); 

如果是java.sql.Date或java.sql.Time,也是同樣的道理。 


 4.在做select、update或insert時,如果某個字段爲日期/時間類型,最好用PreparedStatement,而不要採用Statement 
經常會看到這樣的程序: 
Connection conn;//前面的步驟略 
Statement stmt = conn.createStatement(); 
stmt.execute("insert into tab ( begin_date ) values ( TO_Date( '06/27/2005 12:59:52', 'MM/DD/YYYY HH24:MI:SS'))"); 

熟悉oracle的人都知道,TO_Date是oracle裏的函數,其他數據庫沒有,即使有也很可能不一樣。那麼這段代碼只能用在oracle上,如果換成其他數據庫,程序就無法執行了。 

如果採用PreparedStatement,代碼是這樣: 
Connection conn;//前面的步驟略 
PreparedStatement pstmt = conn.prepareStatement("insert into tab ( begin_date ) values( ?)"); 
pstmt.setTimestamp(1, new Timestamp(System.currentTimeMillis())); 
pstmt.execute(); 
可以看出來,這段代碼與數據庫無關,只要是支持標準sql的數據庫都沒有問題。 
客戶是上帝,想用什麼數據庫,我們就得支持什麼數據庫,爲了避免以後的麻煩,還是用PreparedStatement的好。 


 5.存儲過程的參數,該用日期/時間類型的就要用,不要一味的都採用字符串型 
我發現電信部裏幾乎所有存儲過程,只要是日期/時間,都採用字符串類型(varchar2或其它)。這樣會造成很多麻煩。 
首先,需要約定字符串格式,調用者和被調用者都必須遵循這個格式,這種約定很容易受人爲因素影響; 
其次,存儲過程中需要對字符串做分析,合法性檢查等,增加了編碼的難度和負責度; 
再者,這些額外的代碼,降低的程序的效率,增加了數據庫的負擔。 

採用日期/時間類型來作爲存儲過程的參數,可以降低編碼的難度,從邏輯上看起來更清晰,而且運行效率高。 
在JDBC中採用CallableStatement來調用存儲過程,對日期/時間的輸入和輸出,可以採用setTimestamp,getTimestamp,setDate,getDate,setTime,getTime。 


 6.java.sql.Timestamp如何轉換爲java.util.Date? 
java.sql.Timestamp是java.util.Date的子類,不需要做任何轉換直接賦值即可: 
java.sql.Timestamp ts; 
java.util.Date utilDate; 
utilDate = ts; 

java.sql.Date和java.sql.Time也是一樣的道理。 


 7.java.util.Date如何轉換爲java.sql.Timestamp? 
java.util.Date是java.sql.Timestamp的父類,不能像技巧6那樣做了。要這樣: 
java.sql.Timestamp ts; 
java.util.Date utilDate; 
ts.setTime(utilDate.getTime()); 

java.sql.Date和java.sql.Time也是一樣的道理
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章