👉 歡迎 ,你將獲得: 專屬的計畫實戰 / 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:因公眾號平台更改了推播規則,如果不想錯過內容,記得讀完點一下「在看」,加個「星標」,這樣每次新文章推播才會第一時間出現在你的訂閱列表裏。
點「在看」支持小哈呀,謝謝啦