⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 cnblogs.com/youzhibing/p/18019399 「青石路」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

MyBatis 替换成 MyBatis-Plus

背景介绍

一个老项目,数据库用的是 MySQL 5.7.36 , ORM 框架用的 MyBatis 3.5.0 , mysql-connector-java 版本是 5.1.26

新来了一个干练的小伙,精力充沛,看着就是一个喜欢折腾的主

他就觉得 MyBatis 使用起来不够简单,要写的代码还比较多,觉得有必要替换成 MyBatis-Plus

Mybatis-Plus 替换 Mybatis

先准备一张表 tbl_order,然后初始化 2 条数据

为了简化演示,我就直接用 Mybatis-Plus 搭建一个示例 demo ,以此来模拟下 “小伙” 替换的过程

只是用 MyBatis-Plus 替换 MyBatis ,其他组件的版本暂不动

Mybatis-Plus 版本就用 “小伙” 引用的版本: 3.1.1 ,mysql-connector-java 版本保持不变还是 5.1.26

示例代码:playitsafe

此时运行 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 for type java.time.LocalDateTime

我们再回过头去看看前面说到的异常: Conversion not supported for type java.time.LocalDateTime

Mybatis-Plus 替换 MyBatis 之前没这个异常,替换之后就有了这个异常,这不是 Mybatis-Plus 的问题?

如何找这个异常的根因了?

很简单,直接从异常堆栈入手

点了之后,你会发现方法很简单

这么简单的代码能有什么问题?

大家注意看图中左上角 MyBatis 的版本,是 3.5.1,并不是最初的 3.5.0

有小伙伴可能会问了:不是用 MyBatis-Plus 替换了 MyBatis 吗,怎么还有 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 之前都不支持这些类型

弄清楚这个异常的来龙去脉之后,顺的是不是又理所当然一些了?

暴风雨的来临

版本上线没 2 天,该来的终究还是来了

我们往表 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-issues-1114

无意中看到了这个issue-1114,跟我们前面分析的 Conversion not supported for type java.time.LocalDateTime 是不是同一个问题?

只是我们用到的数据库连接池是默认的 HikariCP 而非 Druid

结合druid/issues/3302来看,如果使用 Druid 作为数据库连接池,出现的异常可能跟我们前面分析的确实不一样

所以大家需要根据自己的实际情况来分析,但针对异常的分析方法是通用的

修了“不该修的Bug”

这是我亲身经历的一次事故,到现在都觉得这锅背的有点冤

文件分为主文件和附属文件,主文件生成之后再生成附属文件

附属文件生成的时候,会校验其依赖的主文件是否都生成了,如果有任意一个主文件未生成,依赖文件不能生成并抛出异常

这个业务还是比较简单吧

但在附属文件校验的优化上,我背上了生产事故

优化前的校验

listFileGenerateLog 作用是根据参数查询文件生成记录,具体实现不用关注

这个校验逻辑是什么?只要有任意一个主文件生成,校验就算通过了,与业务要求(主文件全部生成,才算校验通过)不匹配呀

这不是妥妥的 Bug ?

优化后的校验

碰到 Bug 你能忍?我是忍不了一点,反手就是一个优化

这是不是就符合业务要求了?

生产异常

中午升级之后,稳定运行了一段时间,期间文件正常生成,没出现任何问题

晚上 19 点,有个附属文件生成失败,异常提示: 依赖的资源[abc_{yyyyMMdd}.txt]未生成

当时看到这个异常的第一眼,觉得既熟悉又陌生,熟悉的是这个异常信息的结构,陌生的是 abc_{yyyyMMdd}.txt,这不是文件名吗?

正常来讲应该是 fileId ,是一个自增的正整数呀,怎么会是文件名了?

脑中瞬间闪过一个念头:数据库数据有问题?

一查吓一跳,这个附属文件关联主文件的字段值是:4356,abc_{yyyyMMdd}.txt,看最终修改时间是:2021-08-21 15:22:12.652

4356 文件的文件名就是 abc_{yyyyMMdd}.txt,正常来讲,这个关联字段的值应该是: 4356

敢情这个 校验Bug 完美的兼容了这个脏数据 ,所以几年了,一直没出现异常

是不是有这味了?

这可倒好,我把 Bug 修好,还出现问题了,你说我是不是手贱?

经此一役,我眼里的光又暗淡了些许

总结

关于对组件的升级,或者对旧代码的调整,都有可能牵一发动全身,影响甚大

我的观点是:能不动就不要动,改好没绩效,改出问题要背锅,吃力不讨好,又不是不能跑

如果到了不得不改的地步了,那就需要全面的测试

文章目录
  1. 1. MyBatis 替换成 MyBatis-Plus
    1. 1.1. 背景介绍
    2. 1.2. Mybatis-Plus 替换 Mybatis
    3. 1.3. 升级mysql-connector-java
    4. 1.4. Conversion not supported for type java.time.LocalDateTime
    5. 1.5. 暴风雨的来临
    6. 1.6. mybatis-plus-issues-1114
  2. 2. 修了“不该修的Bug”
    1. 2.1. 优化前的校验
    2. 2.2. 优化后的校验
    3. 2.3. 生产异常
  3. 3. 总结