MyBatis升級踩坑記
前段時間,偶然發現系統某核心模組使用for迴圈插入資料,遂想進行優化,一次批量插入是個不錯的方案,可能可以提高插入速度,肯定可以節約資料庫連線。系統用ORM框架MyBatis做DAO,考慮用MyBatis自帶批量提交功能實現,so easy對吧,但接下來坑一個接一個,想也想不到。
坑一,業務功能需要依賴插入記錄返回記錄id進行下一步操作,單條記錄插入返回id很簡單,配置useGeneratedKeys=”true” keyProperty=”studId”就好;但多條記錄用MyBatis的foreach插入,返回的id卻是null,很沒道理。問同事,他之前也嘗試過,發現不行,沒有深究也說不出個所以然。經查資料,發現這是MyBatis的bug,mybatis3.3.1之前版本,有批量提交不寫回id的bug
祖大俊的部落格
GitHub上MyBatis這個bug
升級MyBatis到3.3.1版本,跨過第一個坑,前途漫漫…..
坑二,專案啟動報錯,錯誤資訊如下,
Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare
經查,專案用到自定義Interceptor,自定義Interceptor類有註解,原註解
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare" , args = { Connection.class}) })
prepare方法簽名在新版本已修改,增加一個Integer引數,新註解
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) }
滿心歡喜再次執行,還是不行,不過這次換了個錯,這個坑算是過了。
坑三,啟動報SpringManagedTransaction錯,具體資訊如下,
Exception in thread "main" java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()Ljava/lang/Integer
什麼原因呢?原來專案還用到mybatis-spring,前面升級mybatis,沒有對應升級mybatis-spring,mybatis-spring版本不夠高導致報錯,升到1.3.1就好了。
版本問題解決,這樣可以了吧!再次執行,不好意思,繼續踩坑。
坑四,報不合法對比錯誤,具體錯誤資訊如下,
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
### Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
什麼原因呢?經查,mapper檔案語句報錯,具體語句如下,
<if test="endTime != null and endTime !='' " >
report_date < #{endTime}
</if>
endTime !=”,這個對比報錯,因為mybatis 3.3.0之後版本對時間引數進行比較時,如果將傳入時間型別引數與空字串進行對比則會引發異常。有人說是mybatis的bug,我覺得不是,因為最新版本3.4.1也有這個問題,可能是新版本mybatis引入了更強的機制。
至此,連踩四個坑後,我決定放棄這次升級,原因是,一方面,專案中有好多endTime !=”這種寫法,馬上要提測版本,一個個修改不現實;另一方面,考慮到可能還有其他未踩到的坑。權衡風險和收益,還是不做升級的好。
通過這次踩坑經歷,我自己總結出兩點經驗,
1. 不要在提版前做大改動,如修改核心模組、升級依賴庫等;
2. 不要太相信開源庫,如mybatis程式碼維護質量還是不高,沒有考慮向前相容,自己做專案要注意。