都说了能不动就别动,非要去调整,出生产事故了吧

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 条数据

 View Code

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

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

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

示例代码:play_it_safe

此时运行 com.qsl.OrderTest#orderListAllTest ,会报错,异常信息如下

 View Code

注意看 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 修好,还出现问题了,你说我是不是手贱?

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

总结

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/712846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 3.1

leetcode hot 100 双指针1.三数之和2.接雨水 多维动态规划1.最长公共子序列 双指针 1.三数之和 三数之和 排序 双指针的方法&#xff0c;固定一个数nums[i], 用两数和找target - nums[i] 的数需要注意两点: 1.需要去掉重复数字 while (l < r && nums[l] nums[…

社交APP开发能给用户带来什么

现在的社交软件也非常的多&#xff0c;每款社交软件都有自己的特色&#xff0c;社交软件是日常中必备的软件&#xff0c;不管是生活交流还是感情工作交流都是比较方便的&#xff0c;因为社交软件满足了日常的远程交流问题&#xff0c;所以开发社交软件也会逐渐的流行起来的。 …

【Qt学习】QLCDNumber的介绍与实例使用(倒计时功能)

文章目录 1. 介绍2. 实例 - QLCDNumber倒计时3. 资源文件 1. 介绍 QLCDNumber是Qt框架中用于显示数字的控件&#xff0c;它模拟了一个液晶数字显示屏。 在Designer界面中显示如下&#xff1a; 有以下 常用属性&#xff1a; 属性描述intValue获取或设置QLCDNumber显示的整数…

js截取图片地址后面的参数和在路径中截取文件名或后缀名

文章目录 前言截取地址 &#xff1f;后面的参数在路径中截取文件名或后缀名总结 前言 在处理网页上的图片资源或者其他类型的文件资源时&#xff0c;你可能会遇到需要使用这些技巧的情况。以下是一些具体的使用场景&#xff1a; 动态修改图片参数&#xff1a;如果你有一个图片U…

【BBuf的CUDA笔记】十四,OpenAI Triton入门笔记三 FusedAttention

0x0. 前言 继续Triton的学习&#xff0c;这次来到 https://triton-lang.org/main/getting-started/tutorials/06-fused-attention.html 教程。也就是如何使用Triton来实现FlashAttention V2。对于FlashAttention和FlashAttention V2网上已经有非常多的介绍了&#xff0c;大家如…

Win11系统安装安卓子系统教程

随着Win11系统的不断普及&#xff0c;以及硬件设备的更新换代&#xff0c;我相信很多同学都已经更新并使用到了最新的Win11系统。那么&#xff0c;Win11系统最受期待的功能“Windows Subsystem for Android”&#xff08;简称WSA&#xff09;&#xff0c;即《安卓子系统》。他可…

spring.factories的常用配置项

概述 spring.factories 实现是依赖 spring-core 包里的 SpringFactoriesLoader 类&#xff0c;这个类实现了检索 META-INF/spring.factories 文件&#xff0c;并获取指定接口的配置的功能。 Spring Factories机制提供了一种解耦容器注入的方式&#xff0c;帮助外部包&am…

掘根宝典之C语言字符串输入函数(gets(),fgets(),get_s())

字符串输入前的注意事项 如果想把一个字符串读入程序&#xff0c;首先必须预留该字符串的空间&#xff0c;然后用输入函数获取该字符串 这意味着必须要为字符串分配足够的空间。 不要指望计算机在读取字符串时顺便计算它的长度&#xff0c;然后再分配空间(计算机不会这样做&a…

ai图生文的软件!分享4个受欢迎的!

在数字化时代&#xff0c;随着人工智能技术的飞速发展&#xff0c;AI图生文软件已经成为自媒体人、创作者和广告从业者手中的得力助手。这些软件能够将静态的图片转化为生动的文字&#xff0c;为图片注入灵魂&#xff0c;让观者仿佛置身于画面之中。今天&#xff0c;就让我们一…

LabVIEW和Python开发微细车削控制系统

LabVIEW和Python开发微细车削控制系统 为满足现代精密加工的需求&#xff0c;开发了一套基于LabVIEW和Python的微细车削控制系统。该系统通过模块化设计&#xff0c;实现了高精度的加工控制和G代码的自动生成&#xff0c;有效提高了微细车削加工的自动化水平和编程效率。 项目…

1950-2022年各省逐年平均降水量数据

1950-2022年各省逐年平均降水量数据 1、时间&#xff1a;1950-2022年 2、指标&#xff1a;省逐年平均降水量 3、范围&#xff1a;33省&#xff08;不含澳门&#xff09; 4、指标解释&#xff1a;逐年平均降水数据是指当年的日降水量的年平均值&#xff0c;不是累计值&#…

ONLYOFFICE 桌面编辑器 v8.0 更新内容详细攻略

文章目录 引言PDF 表单RTL 支持电子表格中的新增功能Moodle 集成用密码保护 PDF 文件从“开始”菜单快速创建文档本地界面主题下载安装桌面编辑工具总结 引言 官网链接&#xff1a; ONLYOFFICE 官方网址 ONLYOFFICE 桌面编辑器是一款免费的文档处理软件&#xff0c;适用于 Li…

uniapp实现-审批流程效果

一、实现思路 需要要定义一个变量, 记录当前激活的步骤。通过数组的长度来循环数据&#xff0c;如果有就采用3元一次进行选择。 把循环里面的变量【name、status、time】, 全部替换为取出的那一项的值。然后继续下一次循环。 虚拟的数据都是请求来的, 组装为好渲染的格式。 二…

【打工日常】使用docker部署在线PDF工具

一、Stirling-PDF介绍 Stirling-PDF是一款功能强大的本地托管的基于 Web 的 PDF 操作工具&#xff0c;使用 docker部署。该自托管 Web 应用程序最初是由ChatGPT全权制作的&#xff0c;现已发展到包含广泛的功能来处理您的所有 PDF 需求。允许对 PDF 文件执行各种操作&#xff0…

基于session注册JAva篇springboot

springboot3全家桶&#xff0c;数据库 &#xff1a;redis&#xff0c;mysql 背景环境&#xff1a;邮箱验证码&#xff0c;验证注册 流程&#xff1a;先通过邮箱验证&#xff0c;发送验证码&#xff0c;将获取到的session和验证码&#xff0c;存入redis里&#xff08;发送邮箱…

【leetcode】链表的回文结构

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 点击查看题目 思路: 1.找中间节点 找中间节点的方法在下面这个博文中详细提过 【点击进入&#xff1a;【l…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:布局约束)

通过组件的宽高比和显示优先级约束组件显示效果。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 aspectRatio aspectRatio(value: number) 指定当前组件的宽高比。 卡片能力&#xff1a; 从API vers…

浅谈 Linux 孤儿进程和僵尸进程

文章目录 前言孤儿进程僵尸进程 前言 本文介绍 Linux 中的 孤儿进程 和 僵尸进程。 孤儿进程 在 Linux 中&#xff0c;就是父进程已经结束了&#xff0c;但是子进程还在运行&#xff0c;这个子进程就被称作 孤儿进程。 需要注意两点&#xff1a; 孤儿进程最终会进入孤儿院…

软考-计算题

1.二维矩阵转换成一维矩阵 2.算术表达式&#xff1a; 3.计算完成项目的最少时间&#xff1a;之前和的max&#xff08;必须之前的所有环节都完成&#xff09; 松弛时间&#xff1a;最晚开始时间-最早开始时间 最早&#xff1a;之前环节都完成的和的max 最晚&#xff1a;总时间…

黑猫的牌面

解法&#xff1a; 桶 #include <iostream> #include <vector> #include <algorithm> using namespace std; #define endl \nint main() {ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);vector<int> tong(1001);int t 4;int k, pai;long lon…