853
京東網上商城
mysql jdbc處理0日期格式蛋疼問題-也算是BUG
最近在寫一個數據庫訪問的中間平台時,使用MySQL JDBC處理一些日期數據,遇到點變態的問題,給大家樂一樂!
首先來看看什麼樣的日期數據這麼蛋疼呢?
DATE 0000-00-00
DATETIME 0000-00-00 00:00:00
TIMESTAMP 0000-00-00 00:00:00
TIME 25:21:22
對於前3種情況,直接用JDBC讀取,肯定會報錯,報錯信息類似這樣:
Value '0000-00-00' can not be represented as java.sql.Date
或者
Value '0000-00-00' can not be represented as java.sql.Timestamp
為什麼?日期值即使是0,也對應到1970-01-01,這種變態的日期格式,不知道那個奇人想出來的。
對於這樣的問題,很多小夥伴想到的第一種辦法就是在jdbc url參數上設置一個:zeroDateTimeBehavior=convertToNull
便可以讓Java程序不報錯了!因為JDBC內部發現是0日期格式,則會轉換為null返回。
驗證中確實可以解決問題,但是,但是,某個用戶的數據庫就是寫入了這樣的一條數據,但是程序確返回了null,用戶認為這並不是他想要的數據(例如在做數據遷移時,目標字段不可空,此時就會報錯),用戶就希望看到的是0000-00-00這樣格式的數據。怎麼辦呢?
首先必須是將參數zeroDateTimeBehavior=convertToNull去掉,否則程序拿到的始終是null,根本不知道數據庫的數據是什麼。但是這樣程序會報錯,不論用getString還是getObject都會報錯。
經過驗證,發現getBytes()不會報錯,然後通過得到的bytes[]數組,new String(bytes[])就可以得到一個這樣的字符串,並且與數據庫內一致。似乎問題解決了?
沒有,更蛋疼的問題出現了,當JDBC啟用流模式或遊標模式時,getBytes()也會報同樣的錯誤,經過驗證發現get各種類型都會報錯,這尼瑪太蛋疼了,沒空看源碼,據我估計,MySQL JDBC在流模式和遊標模式中,對結果集的某些類型轉換處理,沒有複用普通模式(默認是本能地靜態數據)的處理代碼導致了這樣的問題。
但是對於某些大數據的處理,業務應用中必須啟用流模式或遊標模式,因此陷入了一個死套--因此我認為這是MySQL JDBC的一個BUG。
但是用戶的問題必須要解決,為此,不得不去用一下特殊的處理方式,異常判定,我想你看到這裏應該認為這是世界上最土的辦法了,嗬嗬!也就是捕獲上麵描述的Message信息,若發現則認為是0日期格式來解決,準備提交官方BUG,希望盡快能修複吧。
最後來說說Time類型,MySQL這個蛋疼的Time類型是指時長,而不是指日期上的小時:分鍾:秒,因此它的小時數是可以超過24的,但是這樣的值讓Java來解析就會報錯,因此對於MySQL的Time類型處理的時候未了避免問題。通常用getBytes()方式來獲取值,然後用new String(byte[])來得到具體值,當然先要判空。
最後更新:2017-04-03 08:26:28