MyBatis- plus
实战总结
1.批量插入性能
1.批量插入性能差的原因
使用saveBatch()方法时, MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。
查看对应源码
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]);return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, (sqlSession) -> {int size = list.size();int i = 1;for(Iterator var6 = list.iterator(); var6.hasNext(); ++i) {E element = var6.next();consumer.accept(sqlSession, element);if (i % batchSize == 0 || i == size) {sqlSession.flushStatements();}}});}
最终来到了executeBatch()方法,可以看到这很明显是在一条一条循环插入,通过sqlSession.flushStatements()将一个个单条插入的insert语句分批次进行提交,而且是同一个sqlSession,这相比遍历集合循环insert来说有一定的性能提升,但是这并不是sql层面真正的批量插入。
2.解决批量插入性能差方案
通过查阅相关文档后,发现mybatisPlus提供了sql注入器,我们可以自定义方法来满足业务的实际开发需求。
在扩展包下,mybatisPlus还为我们提供了可扩展的可注入方法:
AlwaysUpdateSomeColumnById: 根据Id更新每一个字段,全量更新不忽略null字段,解决mybatis-plus中updateById默认会自动忽略实体中null值字段不去更新的问题;
InsertBatchSomeColumn: 真实批量插入,通过单SQL的insert语句实现批量插入;
Upsert: 更新or插入,根据唯一约束判断是执行更新还是删除,相当于提供insert on duplicate key update支持。
那么现在开始解决批量插入性能差的问题
1.创建自定义sql注入器,并继承DefaultSqlInjector
/*** @author zhmsky* @date 2022/8/15 15:13*/
public class MySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);//更新时自动填充的字段,不用插入值methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));return methodList;}
}
2.将自定义的sql注入器注入到Mybatis容器中
/*** @author zhmsky* @date 2022/8/15 15:15*/
@Configuration
public class MybatisPlusConfig {@Beanpublic MySqlInjector sqlInjector() {return new MySqlInjector();}
}
3.业务开始使用
使用可以继承 BaseMapper 添加自定义方法
/*** @author zhmsky* @date 2022/8/15 15:17*/
public interface CommonMapper<T> extends BaseMapper<T> {/*** 真正的批量插入* @param entityList* @return*/int insertBatchSomeColumn(List<T> entityList);
}
或者直接在业务中使用
public interface CpChickSupplyChainFlockProPreDMapper extends BaseMapper<CpChickSupplyChainFlockProPreD> {/*** 执行 executeBatch()语句实现真正的批量插入* @param entityList* @return*/int insertBatchSomeColumn(Collection<CpChickSupplyChainFlockProPreD> entityList);
}
执行后日志输出
mybatisPlus批量插入性能优化_mybatisplus高效批量_zhm_sky的博客-CSDN博客
2.批量删除性能
和批量插入的原因一样,使用mybatisPlus的IService.removeBatchByIds默认的方法,最后也是一条一条去执行的,性能比较差。
所以在执行批量删除时,不要使用IService的默认方法,应该使用BaseMapper.deleteBatchIds方法,它才是真正的执行了批量操作。
执行日志如下
08:49:12.538 [http-nio-9502-exec-2] DEBUG c.c.p.m.C.deleteBatchIds - [debug,137] - ==> Preparing: DELETE FROM cp_chick_supply_chain_flock_pro_pre_d WHERE id IN ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? )
相关文章:

MyBatis- plus
实战总结 1.批量插入性能 1.批量插入性能差的原因 使用saveBatch()方法时, MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入&a…...

Java --- 期末复习卷
一、单选题 1.所有Java应用程序主类必须有一个名叫( )的方法。[ ] A.method B.main() C.java() D.hello 2.编写并保存了一个Java程序文件之后,( )它。[ …...
File类与IO流相关面试知识(一)
一.java.io.File类 作用:它的作用是用来表示某个文件或文件夹(文件夹又称为目录) 如何用File类的对象表示一个文件或目录的呢? API文档中描述:文件和目录路径名的抽象表示形式 解释:如果要表示一个文件…...

009 - STM32学习笔记 - 中断
009 - STM32学习笔记 - 中断 这节的内容,野火的官方视频我反复看了好几次,但是感觉火哥在这块讲解的特别绕,理解起来很吃力,后来在看了一下其他老师的视频,结合一些书本资料和官方手册,才搞清楚STM32中断该…...
分享几种js格式化金额的方法
一、使用 Intl.NumberFormat 构造函数 这是 JavaScript 中格式化金额的最常见方法。Intl.NumberFormat()构造函数接受两个参数:语言环境和选项。语言环境是为其格式化金额的语言和地区。选项是一组控制金额格式的属性。例如,可以使用样式属性来指定货币…...

圣墟传说H5手工端搭建架设教程
圣墟传说H5手工端搭建架设教程 大家好,我是艾西。今天给大家带来的游戏是由小说改编而来的大型玄幻MMORPG仙侠手游,也是比较老的游戏了虽然你可能没有怎么听过,但总会有一批喜欢的玩家热衷于它。 那么让我们直接进入正题开始操作࿱…...
编程(40)----------单例模式
在简单总结单例模式之前, 需要了解一下背景知识-----为何会有单例模式? 想象一个这样的场景, 打游戏的时候, 尝试很多次, 都未通关. 这种情况下是否会考虑查一下攻略? 一个好的攻略甚至可能连每一关的每一个场景由多少只怪物都说的清清楚楚. 再比如, 在以前上学的时候, 为了…...

Java开发 - 让你少走弯路的Redis主从实现单节点哨兵模式
前言 前一篇中,我们讲解了Redis主从的搭建方式,其实很简单呐有木有,都是配置,连句代码都没有,是不是感觉高估了Redis主从的搭建方式?哈哈,没关系,跟着博主,包你全会。今…...

Java的Atomic原子类
Java SDK 并发包里提供了丰富的原子类,我们可以将其分为五个类别,这五个类别提供的方法基本上是相似的,并且每个类别都有若干原子类。 对基本数据类型的变量值进行原子更新;对对象变量的指向进行原子更新;对数组里面的…...

离线语音控制新方案,NRK3303语音识别芯片在智能风扇的应用
随着科技的不断发展,智能家居已经成为人们日常生活中不可或缺的一部分,涌现出越来越多的智能设备,如智能门锁、智能灯泡、智能冰箱等,这些设备为人们的生活带来了更多的便利和创新。其中作为常见的风扇通过添加智能语音控制功能&a…...
在树莓派3B+上安装Pytorch1.7
在树莓派3B上安装Pytorch1.7(应该是最简单的方法了)_package libopenblas-dev has no installation cand_Chauncey_Wang的博客-CSDN博客由于项目要求,我需要在树莓派上安装pytorch这就有几个问题,首先吧,咱们和外面之间有一道长城,…...

Java性能权威指南-总结4
Java性能权威指南-总结4 Java性能调优工具箱操作系统的工具和分析CPU运行队列磁盘使用率网络使用率 Java监控工具基本的VM信息 Java性能调优工具箱 操作系统的工具和分析 CPU运行队列 快速小结 检查应用性能时,首先应该审查CPU时间。优化代码的目的是提升而不是…...
c语言全局变量和局部变量问题汇总
✅作者简介:嵌入式领域优质创作者,博客专家 ✨个人主页:咸鱼弟 🔥系列专栏:单片机设计专栏 📃推荐一款求职面试、刷题神器👉注册免费刷题 1、关键字static的作用是什么? 定义静态变…...

14.3:给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中字典序最小的结果
给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中字典序最小的结果 贪心写法 首先注意的一点是:如果两个字符串的长度相同,“abc”,“abd”,肯定是“abc”的字典序最…...

C++ 项目实战:跨平台的文件与视频压缩解压工具的设计与实现
C实战:跨平台文件与视频压缩解压工具的设计与实现 一、引言(Introduction)1.1 项目背景与目标1.2 技术选型:C、FFmpeg、libarchive、libzip、QtCFFmpeglibarchivelibzipQt 二、设计思路与框架(Design Philosophy and F…...
C和指针(二)数据
数据类型 1,C语言中仅有四种基本数据类型——整型、浮点型、指针、聚合类型(数组、结构等)。 2,整型包括字符、短整型、整型、长整型,且可以分为有符号和无符号两种版本。 1)长整型至少和整型一样长&#…...
PyTorch基础学习(一)
一.简介 PyTorch是一个基于Python的开源机器学习框架,它提供了丰富的工具和接口,用于构建和训练深度学习模型。PyTorch的主要特点包括: 动态计算图: PyTorch使用动态计算图,这意味着在模型构建过程中可以实时地进行计…...

chatgpt赋能python:Python代做:让您的网站更友好的SEO利器
Python代做:让您的网站更友好的SEO利器 如果您是一位网站管理员或者SEO工程师,您一定知道SEO对于网站的重要性。那么在SEO中,Python代做可以为您提供什么?在本文中,我们将通过介绍Python代做的技术和方法,…...
2022年都快结束了,还有人不会安卓录屏?在安卓上录制屏幕的的实现方式
前言 在我之前的文章 《以不同的形式在安卓中创建GIF动图》 中,我挖了一个坑,可以通过录制屏幕后转为 GIF 的方式来创建 GIF。只是当时我只是提了这么一个思路,并没有给出录屏的方式,所以本文的内容就是教大家如何通过调用系统 A…...
px rem em rpx 区别 用法
任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em16px。那么12px0.75em,10px0.625em。为了简化font-size的换算,需要在css中的body选择器中声明Font-size62.5%,这就使em值变为 16px*62.5%10px, 这样12px1.2em, 10px1em, 也就是说只需要…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...
boost::filesystem::path文件路径使用详解和示例
boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类,封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解,包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...

Python异步编程:深入理解协程的原理与实践指南
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…...