0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Mybatis Plus很好,但也有坑!

jf_ro2CN3Fa 来源:芋道源码 2023-11-27 16:17 次阅读


最近在开发一个后台发送消息的功能时,由于需要给多个用户发送消息,于是使用了 mybatis plus 提供的 saveBatch() 方法,在测试环境测试通过上预发布后,测试反应发送消息接口很慢得等 5、6 秒,于是我就登录线上环境查看执行日志,发现是 mybatis plus 提供的 saveBatch() 方法执行很慢导致,于是也就有了本篇文章。

mybatis plus 是一个流行的 ORM 框架,它基于 mybatis,提供了很多便利的功能,比如代码生成器、通用 CRUD、分页插件、乐观锁插件等。它可以让我们更方便地操作数据库,减少重复的代码,提高开发效率。

案发现场还原

/**
*先保存通知消息,在批量保存用户通知记录
*/
@Transactional(rollbackFor=Exception.class)
@Override
publicbooleansaveNotice(Notifynotify,StringreceiveUserIds){
longbegin=System.currentTimeMillis();
notify.setCreateTime(newDate());
notify.setCreateBy(ShiroUtil.getSessionUid());
if(notify.getPublishTime()==null){
notify.setPublishTime(newDate());
}
booleaninsert=save(notify);
Listcollect=newArrayList<>();
ListreceiveUserList=fillNotifyRecordList(notify,receiveUserIds,collect);
notifyRecordService.saveBatch(collect);
longend=System.currentTimeMillis();
System.out.println(end-begin);
...
returninsert;
}

/**
*根据用户id,组装用户通知记录集合,返回200条记录
*/
publicListfillNotifyRecordList(Notifynotify,StringreceiveUserIds,Listcollect){
ListnoticeRecordList=newArrayList<>(200);
...
//组将两百条用户通知记录
returnnoticeRecordList;
}

如上代码,我有一个 saveNotice() 方法用于保存通知消息以及用户通知记录。执行逻辑如下,

  1. 保存通知消息
  2. 根据用户 id,组装用户通知记录集合,返回 200 条用户通知记录
  3. 批量保存用户通知记录集合

前两步骤耗时都很少,我们直接看第三步操作耗时,结合 sql 执行日志,如下,

--slowsql5542millis.INSERTINTOoa_notify_record(notifyId,receiveUserId,receiveUserName,isRead,createTime)VALUES(?,?,?,?,?)[225,"fcd90fe3990e505d07c90a238f75e9c1","niuwawa",false,"2023-10-302304"]
5681

再结合 mybatis free log 插件打印完整 sql 如下图,

321d25c6-8cc5-11ee-939d-92fbcf53809c.png

可以看出,我们批量保存用户通知记录是一条记录一条进行保存得,已经可以猜测就是批量插入方法导致得耗时较高。

这里使用得是 mybatis log free 插件,它可以自动帮我们在控制台打印完整得 mybatis sql 语句。有需要可以在 idea 插件中心搜索 mybatis log free 下载安装。

结合 saveBatch() 底层源码也能够看出,mybatis plus 对于批量操作是通过 for 循环执行保存操作得,源码如下图,

322e80aa-8cc5-11ee-939d-92fbcf53809c.png

到这里我们也就知道了在测试环境执行较快得原因,因为在测试环境需要批量保存得用户通知记录比较少,只有几条记录,所以很快。但是上预发布后,由于预发布中需要批量保存得用户通知记录比较多达到了数百条,所以执行较慢,耗时达到了 5、6 秒之久。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

解决方法

到这里,也就是本文得重点所在了,那怎么解决这个问题嘞?如何既利用 mybatis plus 提供得便携性,也能够解决批量操作耗时较高得问题。

其实解决方法很简单,只需要在 jdbcurl 上添加 rewriteBatchedStatements=true 参数即可解决这个问题。

MySQL 的 JDBC 连接的 url 中要加 rewriteBatchedStatements 参数,并保证 5.1.13 以上版本的驱动,才能实现高性能的批量插入。

MySQL JDBC 驱动在默认情况下会无视 executeBatch()语句,把我们期望批量执行的一组 sql 语句拆散,一条一条地发给 MySQL 数据库,批量插入实际上是单条插入,直接造成较低的性能。只有把 rewriteBatchedStatements 参数置为 true, 驱动才会帮你批量执行 SQL。另外这个选项对 INSERT/UPDATE/DELETE 都有效。

rewriteBatchedStatements=true 的意思是,当你在 Java 程序中使用批量插入/修改/删除(batching)时,MySQL JDBC 驱动程序将尝试重新编写(rewrite)你的 SQL 语句,以便更有效地执行这些批量插入操作。

OK,在我们给 jdbcurl 上添加了参数后,看看效果,如下图,

325f6e2c-8cc5-11ee-939d-92fbcf53809c.png

可以看到 jdbcurl 添加了 rewriteBatchedStatements=true 参数后,批量操作的执行耗时已经只有 200 毫秒,自此也就解决了 mybatis plus 提供的 saveBatch() 方法执行耗时较高得问题。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

总结

mybatis plus 给开发人员带来了很多便利,但是其中也有一些坑点,比如上文所提到得批量操作耗时问题,如果不注意的话,就有可能调入坑里,各位开发同学可以检查自己或者公司项目中 jdbcurl 是否缺失 rewriteBatchedStatements=true 参数,加以改正,避免重复掉入这个坑里。



声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3765

    浏览量

    64276
  • 生成器
    +关注

    关注

    7

    文章

    313

    浏览量

    20977
  • mybatis
    +关注

    关注

    0

    文章

    58

    浏览量

    6700

原文标题:Mybatis Plus很好,但也有坑!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    mybatis plus的常规用法

    上篇文章我们介绍过通过 Mybatis Plus 进行增删改查,如下这段代码: /** * 根据id修改 * UPDATE user SET user_name=?, user_age
    的头像 发表于 09-25 15:06 876次阅读
    <b class='flag-5'>mybatis</b> <b class='flag-5'>plus</b>的常规用法

    Mybatis的内部设计介绍

    Mybatis源码分析-整体设计(一)
    发表于 06-06 09:43

    MyBatis的整合

    SpringBoot-15-之整合MyBatis-注解篇+分页
    发表于 10-28 08:09

    Mybatis是什么

    Mybatis第一讲
    发表于 06-04 15:33

    mybatis快速入门

    本文详细介绍了mybatis相关知识,以及mybatis快速入门步骤详解。
    的头像 发表于 02-24 09:41 3474次阅读
    <b class='flag-5'>mybatis</b>快速入门

    一篇让你熟练掌握 MyBatis-Plus

    MyBatis-plus 是一款 Mybatis 增强工具,用于简化开发,提高效率。下文使用缩写 mp来简化表示 MyBatis-plus,本文主要介绍 mp 搭配 Spring Boot
    的头像 发表于 06-01 09:30 2574次阅读
    一篇让你熟练掌握 <b class='flag-5'>MyBatis-Plus</b>!

    Mybatis-Plus Mybatis增强工具包

    ./oschina_soft/gitee-mybatis-plus.zip
    发表于 06-13 11:34 1次下载
    <b class='flag-5'>Mybatis-Plus</b> <b class='flag-5'>Mybatis</b>增强工具包

    easy-mybatis Mybatis的增强框架

    ./oschina_soft/gitee-easy-mybatis.zip
    发表于 06-14 09:45 1次下载
    easy-<b class='flag-5'>mybatis</b> <b class='flag-5'>Mybatis</b>的增强框架

    MyBatis-Plus的使用与测试

    本文主要介绍mybatis-plus这款插件,针对springboot用户。包括引入,配置,使用,以及扩展等常用的方面做一个汇总整理,尽量包含大家常用的场景内容。
    的头像 发表于 08-22 11:56 1290次阅读

    Fluent Mybatis、原生MybatisMybatis Plus对比

    mapper中再组装参数。那对比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?
    的头像 发表于 09-15 15:41 1404次阅读

    MyBatis-Plus为什么不支持联表

    MyBatis Plus Join`一款专门解决MyBatis Plus 关联查询问题的扩展框架,他并不一款全新的框架,而是基于`MyBatis
    的头像 发表于 02-28 15:19 2405次阅读
    <b class='flag-5'>MyBatis-Plus</b>为什么不支持联表

    介绍一款基于Mybatis-Plus的代码自助生成器

    在基于Mybatis的开发模式中,很多开发者还会选择Mybatis-Plus来辅助功能开发,以此提高开发的效率。
    的头像 发表于 05-23 14:16 1124次阅读
    介绍一款基于<b class='flag-5'>Mybatis-Plus</b>的代码自助生成器

    如何调优MyBatis 25倍性能

    最近在压测一批接口,发现接口处理速度慢的有点超出预期,感觉很奇怪,后面定位发现是数据库批量保存这块很慢。 这个项目用的是 mybatis-plus,批量保存直接用的是 mybatis-plus 提供的 saveBatch。 我点进去看了下源码,感觉有点不太对劲
    的头像 发表于 05-30 09:56 579次阅读
    如何调优<b class='flag-5'>MyBatis</b> 25倍性能

    MyBatis Plus如何简化开发

    本篇文章,我们通过 MyBatis Plus 来对一张表进行 CRUD 操作,来看看是如何简化我们开发的。 1、创建测试表 创建 USER 表: DROP TABLE IF EXISTS
    的头像 发表于 10-09 15:08 400次阅读
    <b class='flag-5'>MyBatis</b> <b class='flag-5'>Plus</b>如何简化开发

    mybatis和mybatisplus的区别

    MyBatisMyBatis Plus是两个非常受欢迎的Java持久层框架。这两个框架在设计和功能上有一些区别,下面我将详细介绍它们之间的差异以及各自的特点。 设计理念与目标: MyBati
    的头像 发表于 12-03 11:53 2487次阅读