閱讀853 返回首頁    go 京東網上商城


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

  上一篇:go 淘寶數據庫OceanBase SQL編譯器部分 源碼閱讀--解析SQL語法樹
  下一篇:go 使用PHP和AJAX製作日曆