当前位置: 首页 > news >正文

MyBatis-plus的批量插入方式对比分析

MyBatis-plus的批量插入方式对比分析

  【摘要】Mybatis批量插入一直是开发者重点关注的问题,本文列举了Mybatis的五种插入方式进行对比分析,验证了五种批量插入的方式的优先级。

1 准备工作

1.1 新建spring项目

  略。

1.2 导入pom.xml依赖

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency><!--Mybatis依赖-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version>
</dependency><!--Mybatis-Plus依赖-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>

1.3 配置yml文件

server:port: 8080spring:datasource:username: mysql用户名password: mysql密码url: jdbc:mysql://localhost:3306/数据库名字?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapping/*.xml

1.4 创建插入模型

@Data
public class User {private int id;private String username;private String password;
}

2 测试

2.1 Mybatis利用For循环批量插入

1、编写UserService服务类,测试一万条数据的耗时情况:

@Service
public class UserService {@Resourceprivate UserMapper userMapper;public void InsertUsers(){long start = System.currentTimeMillis();for(int i = 0 ;i < 10000; i++) {User user = new User();user.setUsername("name" + i);user.setPassword("password" + i);userMapper.insertUsers(user);}long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end-start) + "ms" );}}

2、编写UserMapper接口

@Mapper
public interface UserMapper {Integer insertUsers(User user);
}

3、编写UserMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ithuang.demo.mapper.UserMapper"><insert id="insertUsers">INSERT INTO user (username, password)VALUES(#{username}, #{password})</insert>
</mapper>

4、进行单元测试

@SpringBootTest
class DemoApplicationTests {@Resourceprivate UserService userService;@Testpublic void insert(){userService.InsertUsers();}
}

5、输出结果
  一万条数据耗时26348ms

2.2 MyBatis的手动批量提交

1、其他保持不变,Service层作稍微的变化

@Service
public class UserService {@Resourceprivate UserMapper userMapper;@Resourceprivate SqlSessionTemplate sqlSessionTemplate;public void InsertUsers(){//关闭自动提交SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);UserMapper userMapper = sqlSession.getMapper(UserMapper.class);long start = System.currentTimeMillis();for(int i = 0 ;i < 10000; i++) {User user = new User();user.setUsername("name" + i);user.setPassword("password" + i);userMapper.insertUsers(user);}sqlSession.commit();long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end-start) + "ms" );}
}

2、结果输出
  一万条数据总耗时:24516ms。

2.3 Mybatis以集合方式批量新增

1、编写UserService服务类

@Service
public class UserService {@Resourceprivate UserMapper userMapper;public void InsertUsers(){long start = System.currentTimeMillis();List<User> userList = new ArrayList<>();User user;for(int i = 0 ;i < 10000; i++) {user = new User();user.setUsername("name" + i);user.setPassword("password" + i);userList.add(user);}userMapper.insertUsers(userList);long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end-start) + "ms" );}
}

2、编写UserMapper接口

@Mapper
public interface UserMapper {Integer insertUsers(List<User> userList);
}

3、编写UserMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ithuang.demo.mapper.UserMapper"><insert id="insertUsers">INSERT INTO user (username, password)VALUES<foreach collection ="userList" item="user" separator =",">(#{user.username}, #{user.password})</foreach></insert>
</mapper>

4、输出结果
  一万条数据总耗时:521ms

2.4 MyBatis-Plus提供的SaveBatch方法

1、编写UserService服务

@Service
public class UserService extends ServiceImpl<UserMapper, User> implements IService<User> {public void InsertUsers(){long start = System.currentTimeMillis();List<User> userList = new ArrayList<>();User user;for(int i = 0 ;i < 10000; i++) {user = new User();user.setUsername("name" + i);user.setPassword("password" + i);userList.add(user);}saveBatch(userList);long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end-start) + "ms" );}
}

2、编写UserMapper接口

@Mapper
public interface UserMapper extends BaseMapper<User> {}

3、单元测试结果

  一万条数据总耗时:24674ms

2.5 MyBatis-Plus提供的InsertBatchSomeColumn方法

1、编写EasySqlInjector 自定义类

public class EasySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {// 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));return methodList;}}

2、定义核心配置类注入此Bean

@Configuration
public class MybatisPlusConfig {

@Bean
public EasySqlInjector sqlInjector() {return new EasySqlInjector();
}

}
3、编写UserService服务类

public class UserService{@Resourceprivate UserMapper userMapper;public void InsertUsers(){long start = System.currentTimeMillis();List<User> userList = new ArrayList<>();User user;for(int i = 0 ;i < 10000; i++) {user = new User();user.setUsername("name" + i);user.setPassword("password" + i);userList.add(user);}userMapper.insertBatchSomeColumn(userList);long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end-start) + "ms" );}
}

4、编写EasyBaseMapper接口

public interface EasyBaseMapper<T> extends BaseMapper<T> {/*** 批量插入 仅适用于mysql** @param entityList 实体列表* @return 影响行数*/Integer insertBatchSomeColumn(Collection<T> entityList);
}

5、编写UserMapper接口

@Mapper
public interface UserMapper<T> extends EasyBaseMapper<User> {}

6、单元测试结果

  一万条数据总耗时:575ms

2.6 JDBC原生的批量插入

1、编写JDBC池化工具类

public class JDBCDruidUtils {private static DataSource dataSource;private static Connection conn;/*创建数据Properties集合对象加载加载配置文件*/static {Properties pro = new Properties();//加载数据库连接池对象try {//获取数据库连接池对象pro.load(JDBCDruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"));dataSource = DruidDataSourceFactory.createDataSource(pro);} catch (Exception e) {e.printStackTrace();}}/*获取连接*/public static Connection getConnection() throws SQLException {return dataSource.getConnection();}/*** 关闭conn,和 statement独对象资源** @param connection* @param statement* @MethodName: close* @return: void*/public static void close(Connection connection, Statement statement) {if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 关闭 conn , statement 和resultset三个对象资源** @param connection* @param statement* @param resultSet* @MethodName: close* @return: void*/public static void close(Connection connection, Statement statement, ResultSet resultSet) {close(connection, statement);if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {             e.printStackTrace();}}}/*获取连接池对象*/public static DataSource getDataSource() {return dataSource;}
}
# druid.properties配置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username=用户名
password=密码
initialSize=10
maxActive=50
maxWait=60000

2、编写UserService服务类

public void InsertUsersByJdbc() {long start = System.currentTimeMillis();Connection connection = null;PreparedStatement ps = null;try {connection = JDBCDruidUtils.getConnection();//控制事务:默认不提交connection.setAutoCommit(false);String sql = "INSERT INTO user (username, password) VALUES (?, ?)";ps = connection.prepareStatement(sql);User user;for (int i = 0; i < 1000000; i++) {user = new User();user.setUsername("name" + i);user.setPassword("password" + i);ps.setString(1, user.getUsername());ps.setString(2, user.getPassword());//将一组参数添加到此 PreparedStatement 对象的批处理命令中。ps.addBatch();}//执行批处理ps.executeBatch();//手动提交事务connection.commit();} catch (SQLException e) {throw new RuntimeException(e);} finally {JDBCDruidUtils.close(connection, ps);}long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end - start) + "ms");}

3、输出结果
  1万数据总耗时19000ms。

3 总结

  大量数据的场景下性能对比:InsertBatchSomeColumn>自定义xml以集合的方式>Jdbc原生>SaveBatch>手动for循环批量>自动for循环批量。
  网上很多人都说JDBC原生性能很好,但是我发现其非常差,有可能是我使用的是mybatis-plus依赖,如果这是推论正确,那就可以证明mybatis-plus在mybatis的基础上不仅增强了功能也增强了性能。所以可以得出结论:开发中用mybatis-plus是没有错的,如果想提高性能,只能实施其他方案,比如分库分表,千万别想着JDBC原生性能更好。

相关文章:

MyBatis-plus的批量插入方式对比分析

MyBatis-plus的批量插入方式对比分析 【摘要】Mybatis批量插入一直是开发者重点关注的问题&#xff0c;本文列举了Mybatis的五种插入方式进行对比分析&#xff0c;验证了五种批量插入的方式的优先级。 1 准备工作 1.1 新建spring项目 略。 1.2 导入pom.xml依赖 <depende…...

【系分论文】论软件开发模型及应用

目录 论题论题介绍论文要点理论素材准备范文摘要正文 论文补充知识 论题 论软件开发模型及应用 论题介绍 软件开发模型&#xff08; Software Development Model&#xff09;是指软件开发全部过程、活动和任务的结构框架。软件开发过程包括需求、设计、编码和测试等阶段&…...

渗透测试--5.3.使用john破解密码

前言 由于Linux是Internet最流行的服务器操作系统&#xff0c;因此它的安全性备受关注。这种安全主要靠口令实现。 Linux使用一个单向函数crypt&#xff08;&#xff09;来加密用户口令。单向函数crypt&#xff08;&#xff09;从数学原理上保证了从加密的密文得到加密前的明…...

Go中的变量类型

Go中的变量类型 1.为什么要使用变量 变量其实指定的是一段内存地址&#xff0c;根据这个内存地址可以找到我们需要找到的东西。 2.变量类型 变量的功能就是用来存储数据的&#xff0c;根据不同的数据类型可以存储不同的数据。常见的变量的类型 整型、浮点型、布尔型等。变…...

基于STM32的NRF24L01 2.4G通讯模块的驱动实验(HAL库)

前言&#xff1a;本文为手把手教学NRF24L01 2.4G通讯模块的驱动实验&#xff0c;本教程的 MCU 采用STM32F103ZET6与STM32F103C8T6&#xff0c;彼此进行互相通讯。通过 CubeMX 软件配置 SPI 协议驱动NRF24L01 2.4G通讯模块&#xff08;HAL库&#xff09;。NRF24L01 2.4G是嵌入式…...

DJ5-3 多路访问链路和协议

目录 一、网络链路 二、广播信道要解决问题 三、多路访问协议 1、基本介绍 2、多路访问协议的类型&#xff08;3&#xff09; 四、信道划分协议 1、时分多路访问 TDMA 2、频分多路访问 FDMA 3、码分多路访问 CDMA&#xff08;略&#xff09; 五、随机访问协议 1、纯…...

技术领导力?

作品集&#xff08;Portfolio&#xff09;会比简历&#xff08;Resume&#xff09;更有参考意义。 怎么才算有技术领导力&#xff1f; 1) 能够发现问题&#xff0c;并能够提供解决问题的思路和方案&#xff0c;并能比较方案的优缺点。 2) 能用更简洁有效的方式解决问题。 3…...

计算机的基本工作原理

参考资料&#xff1a; L-1.6: Common Bus system| How basic computer works - YouTube 准备好内存单元、不同类型的寄存器&#xff0c;内存和寄存器、寄存器和寄存器之间都是通过总线连接(假设是直接把数据总线、控制总线、地址总线变成一条总线)。 使用多路复用器实现的总线&…...

【论文简述】Cross-Attentional Flow Transformer for Robust Optical Flow(CVPR 2022)

一、论文简述 1. 第一作者&#xff1a;Xiuchao Sui、Shaohua Li 2. 发表年份&#xff1a;2021 3. 发表期刊&#xff1a;arxiv 4. 关键词&#xff1a;光流、Transformer、自注意力、交叉注意力、相关体 5. 探索动机&#xff1a;由于卷积的局部性和刚性权重&#xff0c;有限…...

【JAVA】Java中方法的使用,理解方法重载和递归

目录 1.方法的概念及使用 1.1什么是方法 1.2方法的定义 1.3方法调用的执行过程 1.4实参和形参 2.方法重载 2.1为什么需要使用方法重载 2.2什么是方法重载 3.递归 3.1什么是递归 3.2递归执行的过程 3.3递归的使用 1.方法的概念及使用 1.1什么是方法 方法就是一个代…...

高级网络计算模式复习

P2P 对等网络&#xff08;Peer-to-Peer Networks&#xff09;是分布式系统和计算机网络相结合的产物&#xff0c;在应用领域和学术界获得了广泛的重视和成功&#xff0c;被称为“改变Internet的一代网络技术”。 peer指网络结点&#xff0c;在行为上是自由的——任意加入、退…...

【笔试强训选择题】Day15.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言 一、…...

图论专题(一)

图论专题(一) 参考文献 BFS和DFS的直观解释 https://blog.csdn.net/c406495762/article/details/117307841Leetcode岛屿问题系列分析 https://blog.csdn.net/qq_39144436/article/details/124173504多源广度优先 https://blog.csdn.net/peko1/article/details/121989497拓扑排…...

新星计划2023【网络应用领域基础】————————Day4

常见的网络基础介绍 前言 我们学习了一些基础的网络协议&#xff0c;以及子网掩码和vlan&#xff0c;同时也做了个简单的单臂路由实验 这篇文章我将仔细的讲解单臂路由的应用和交换机二层接口类型&#xff0c;以及wireshark的教程。 一&#xff0c;交换机二层接口 交换机的二…...

[CTF/网络安全] 攻防世界 view_source 解题详析

[CTF/网络安全] 攻防世界 view_source 解题详析 查看页面源代码方式归类总结 题目描述&#xff1a;X老师让小宁同学查看一个网页的源代码&#xff0c;但小宁同学发现鼠标右键好像不管用了。 查看页面源代码方式归类 单击鼠标右键&#xff0c;点击查看页面源代码&#xff1a; …...

目前流行的9大前端框架

1. React 2. Vue 3. Angular 、 4. Svelte 官网&#xff1a;https://svelte.dev 中文官网&#xff1a;https://www.sveltejs.cn Svelte 是一种全新的构建用户界面的方法。传统框架如 React 和 Vue 在浏览器中需要做大量的工作&#xff0c;而 Svelte 将这些工作放到构建应用程…...

【mysql】explain执行计划之select_type列

目录 一、说明二、示例2.1 simple&#xff1a;简单表&#xff0c;不使用union或者子查询2.2 primary&#xff1a;主查询&#xff0c;外层的查询2.3 subquery&#xff1a;select、where之后包含了子查询&#xff0c;在select语句中出现的子查询语句&#xff0c;结果不依赖于外部…...

网易云音乐开发--音乐播放暂停切换上下首功能实现

音乐播放暂停功能实现 封装一个控制音乐播放/暂停的功能函数 看一下文档&#xff0c;我需要用的api 这个接口好像没有音频的url&#xff0c;查看一下&#xff0c;换个api 这样就能拿到id&#xff0c;并可以播放了 但是音乐并没有播放 我们少了这个 现在可以播放了&#xff…...

如何学习网络安全?

近半年我一直在整理网络安全相关资料&#xff0c;对于网络安全该怎么入门我谈谈我的看法&#xff0c;网络安全一直处于法律的边缘&#xff0c;学的不好或者剑走偏锋一下子人就进去了&#xff0c;所以我建议入门前先熟读《网络安全法》&#xff0c;除此之外还有《互联网安全产品…...

软件测试适合女生吗?

大家好&#xff0c;我是程序员馨馨&#xff0c;一个混过大厂&#xff0c;待过创业公司&#xff0c;有着 6 年工作经验的软件测试妹纸一枚。之前在也写过几篇文章&#xff0c;之后很多朋友过来咨询女生能不能做软件测试。 今天索性写篇文章&#xff0c;详细的介绍一下软件测试&a…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...