當前位置: 妍妍網 > 碼農

公司新來小夥,把 MyBatis 替換成 MyBatis-Plus,上線後被開了.....

2024-05-30碼農

來源:程式設計師江小北

👉 歡迎 ,你將獲得: 專屬的計畫實戰 / Java 學習路線 / 一對一提問 / 學習打卡 / 每月贈書

新計畫: 仿小紅書 (微服務架構)正在更新中... , 全棧前後端分離部落格計畫 2.0 版本完結啦, 演示連結 http://116.62.199.48/ 。全程手摸手,後端 + 前端全棧開發,從 0 到 1 講解每個功能點開發步驟,1v1 答疑,直到計畫上線。 目前已更新了261小節,累計43w+字,講解圖:1806張,還在持續爆肝中.. 後續還會上新更多計畫,目標是將Java領域典型的計畫都整一波,如秒殺系統, 線上商城, IM即時通訊,Spring Cloud Alibaba 等等,

背景簡介

在一個老計畫中,資料庫采用的是 MySQL 5.7.36,ORM 框架使用的是 MyBatis 3.5.0,而 mysql-connector-java 的版本是 5.1.26。

有一天,一個精力充沛、充滿折騰精神的年輕人加入了計畫。

他覺得 MyBatis 的使用不夠簡單,需要寫的程式碼比較多,因此認為有必要將其替換為 MyBatis-Plus。

MyBatis-Plus 替換 MyBatis

首先,我們準備了一張名為 tbl_order 的表,並初始化了其中的兩條數據。

DROP TABLE IF EXISTS `tbl_order`;
CREATE TABLE `tbl_order` (
`id` bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
`order_no` varchar(50) NOT NULL COMMENT '訂單號',
`pay_time` datetime(3) DEFAULT NULL COMMENT '付款時間',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '建立時間',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '最終修改時間',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '訂單';
INSERT INTO `tbl_order` VALUES (1, '123456''2024-02-21 18:38:32.000''2024-02-21 18:37:34.000''2024-02-21 18:40:01.720');
INSERT INTO `tbl_order` VALUES (2, '654321''2024-02-21 19:33:32.000','2024-02-21 19:32:12.020''2024-02-21 19:34:03.727');

為了簡化演示,我們直接使用 MyBatis-Plus 構建了一個範例 demo,以此來模擬這位年輕人的替換過程。

我們只是簡單地將 MyBatis-Plus 替換了 MyBatis,而其他元件的版本保持不變。

我們使用的 MyBatis-Plus 版本是這位年輕人參照的版本:3.1.1,

mysql-connector-java 的版本保持不變,仍然是 5.1.26。

範例程式碼:play_it_safe

然後,執行 com.qsl.OrderTest#orderListAllTest ,卻遇到了報錯,異常資訊如下所示:

請註意 Caused by 部份。

圖片

不支持的轉換型別: java.time.LocalDateTime

是誰不支持呢?是 mysql-connector-java 不支持!

那麽,哪個版本的 mysql-connector-java 支持呢?

答案是:5.1.37

圖片

升級 mysql-connector-java

我們將 mysql-connector-java 升級到 5.1.37,然後再次執行 com.qsl.OrderTest#orderListAllTest

圖片

這次不再報異常,並且查詢結果也是正確的。

看起來,MyBatis-Plus 替換 MyBatis 的任務完成了。

這一切都如此順利,讓人有些懷疑。

圖片

讓我們再回頭看看之前提到的異常:

Conversion not supported fortype java.time.LocalDateTime

在替換 MyBatis 之前並沒有這個異常,但在替換之後就出現了這個異常,這難道不是 MyBatis-Plus 的問題嗎?

那麽如何找到這個異常的根本原因呢?

其實很簡單,直接從異常堆疊入手。

圖片

點選後,你會發現程式碼非常簡單。

圖片

這麽簡單的程式碼怎麽會有問題呢?

大家請註意圖中左上角的 MyBatis 版本,是 3.5.1,而不是最初的 3.5.0。

可能有人會問: 「既然替換成了 MyBatis-Plus,為什麽還有 Mybatis 的存在?」

這個問題問得確實好,我只想給你個大嘴巴。

圖片

現在讓我們看一下 MyBatis-Plus 的官方說明。

圖片

既然基於 Mybatis 3.5.0 沒有丟擲異常,而基於 3.5.1 卻丟擲了異常。

「LocalDateTimeTypeHandler」 在 3.5.1 中肯定進行了調整

那我們來看看調整了什麽?

圖片

看出什麽了嗎?

MyBatis 3.5.0 會處理 LocalDateTime 型別的轉換(將 java.sql.Timestamp 轉換成 java.time.LocalDateTime )。

然而,註意了啊,最關鍵的地方來了!

從 MyBatis 3.5.1 開始,不再處理 LocalDateTime (還包括:LocalDate、LocalTime)型別的轉換,而是交由 JDBC 元件,也就是 mysql-connector-java 來實作。

而巧的是:

mysql-connector-java 5.1.26 不支持型別 LocalDateTime。

圖片

那麽它支持哪些型別呢?

我們同樣從異常堆疊入手。

圖片

點選後,可以看到下圖。

圖片

往上滑動滑鼠,就可以看到支持的型別。

確實沒有 LocalDateTime、LocalDate 和 LocalTime。

mysql-connector-java 5.1.37 開始支持 LocalDateTime、LocalDate 和 LocalTime,前面已經介紹過了,不再贅述。

總結異常根本原因:

MyBatis 3.5.1 開始不再處理 LocalDateTime、LocalDate 和 LocalTime 的轉換,而 mysql-connector-java 5.1.37 之前都不支持這些型別。

搞清楚了這個異常的來龍去脈,順理成章的感覺是不是又回來了?

暴風雨來臨

版本上線不到兩天,該來的終究還是來了。

我們往表 tbl_order 中插入了一條記錄:

INSERT INTO tbl_order 
VALUES (3, 'asdfgh', NULL, '2024-02-21 20:01:31.111''2024-02-21 20:02:56.764');

然後再次執行 com.qsl.OrderTest#orderListAllTest

圖片

此時我就想問這位年輕人:爽不爽?

圖片

遇到了異常,那就找出原因。

同樣從異常堆疊入手。

圖片

看出什麽了嗎?

如果 getTimestamp(columnIndex) 得到的是 NULL,那不就是 NullPointerException ?這也太不嚴謹了吧?

修復問題是當務之急,先看哪個版本進行了修復?

圖片

將 mysql-connector-java 升級到 5.1.42。

圖片

問題得以修復。

經過這一次事件,這位年輕人似乎成長了許多,但眼中的光卻黯淡了不少。

Mybatis-Plus 的問題

無意中我看到了這個 issue-1114,是不是和我們之前分析的 「 Conversion not supported for type java.time.LocalDateTime 」 是同一個問題?

只是我們使用的資料庫連線池是預設的 HikariCP 而非 Druid。

結合 druid/issues/3302 ,如果使用 Druid 作為資料庫連線池,出現的異常可能與我們之前分析的確實不同。

因此,大家需要根據自己的實際情況進行分析,但對異常的分析方法是通用的。

總結

關於元件的升級或舊程式碼的調整,都可能引發連鎖反應,影響重大。

我的觀點是:

能不動就不要動,改好沒功勞,改壞要背鍋,吃力不討好,又不是必須要改。

如果不得不改,那就需要全面的測試。

👉 歡迎 ,你將獲得: 專屬的計畫實戰 / Java 學習路線 / 一對一提問 / 學習打卡 / 每月贈書

新計畫: 仿小紅書 (微服務架構)正在更新中... , 全棧前後端分離部落格計畫 2.0 版本完結啦, 演示連結 http://116.62.199.48/ 。全程手摸手,後端 + 前端全棧開發,從 0 到 1 講解每個功能點開發步驟,1v1 答疑,直到計畫上線。 目前已更新了261小節,累計43w+字,講解圖:1806張,還在持續爆肝中.. 後續還會上新更多計畫,目標是將Java領域典型的計畫都整一波,如秒殺系統, 線上商城, IM即時通訊,Spring Cloud Alibaba 等等,


1. 

2. 

3. 

4. 

最近面試BAT,整理一份面試資料Java面試BATJ通關手冊,覆蓋了Java核心技術、JVM、Java並行、SSM、微服務、資料庫、數據結構等等。

獲取方式:點「在看」,關註公眾號並回復 Java 領取,更多內容陸續奉上。

PS:因公眾號平台更改了推播規則,如果不想錯過內容,記得讀完點一下在看,加個星標,這樣每次新文章推播才會第一時間出現在你的訂閱列表裏。

「在看」支持小哈呀,謝謝啦