当前位置: 首页 > 后端技术 > Java

MyBatis批量插入数据的3种方式!

时间:2023-04-01 16:30:04 Java

批量插入功能是我们日常工作中比较常见的业务功能之一。之前也写过一篇关于《MyBatis Plus 批量数据插入功能,yyds!》的文章,但是评论区的反馈不是很好。主要有两个问题:第一,很多人误解了MyBatisPlus(以下简称MP)的批量插入功能,认为MP也是使用循环一次性插入数据,所以性能并没有提升;其次,原生的批量插入方式其实很坑,但鲜为人知。所以基于以上情况,雷哥决定对MyBatis批量插入做一个总结,同时对三种实现方式做一个性能测试,以及相应的原理分析。简单说一下三个批量插入函数:循环单次插入;MP批量插入功能;本机批量插入功能。在准备工作开始之前,让我们创建数据库和测试数据。执行的SQL脚本如下:-------------------------------CREATEDATABASE------------------------------设置名称utf8mb4;设置FOREIGN_KEY_CHECKS=0;如果存在`testdb`,则删除数据库;CREATEDATABASE`testdb`;USE`testdb`;--------------------------------创建用户表------------------------------如果存在`user`则删除表;创建表`user`(`id`int(11)不是NULLAUTO_INCREMENT,`name`varchar(255)CHARACTERSETutf8mb4COLLATEutf8mb4_binNULLDEFAULTNULL,`password`varchar(255)CHARACTERSETutf8mb4COLLATEutf8mb4_binNULLDEFAULTNULL,`createtime`datetimeNULLDEFAULTCURRENT_TIMESTAMP,)ENGINE=InnoDBCHARCEMENT_SET_INGIN=utf8mb4COLLATE=utf8mb4_binROW_FORMAT=动态;------------------------------添加测试数据----------------------------INSERTINTO`user`VALUES(1,'ZhaoYun','123456','2021-09-1018:11:16');INSERTINTO`user`VALUES(2,'张飞','123456','2021-09-1018:11:28');INSERTINTO`user`VALUES(3,'关羽','123456','2021-09-1018:11:34');INSERTINTO`user`VALUES(4,'刘备','123456','2021-09-1018:11:41');INSERTINTO`user`VALUES(5,'曹操','123456','2021-09-1018:12:02');设置FOREIGN_KEY_CHECKS=1;最终数据库效果如下:1.循环单次插入接下来我们使用SpringBoot项目批量插入10W条数据分别测试每个方法的执行时间循环单插入的(测试)核心代码如下:importcom.example.demo.model.User;importcom.example.demo.service.impl.UserServiceImpl;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;@SpringBootTestclassUserControllerTest{//最大周期数privatestaticfinalintMAXCOUNT=100000;@AutowiredprivateUserServiceImpl用户服务;/***循环单次插入*/@Testvoidsave(){longstime=System.currentTimeMillis();//统计开始时间for(inti=0;icom.baomidoumybatis-plus-boot-startermybatis-plus-latest-version注:mybatis-plus-latest-version表示最新版本MP框架的编号,可以访问https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter查询最新的版本号,但是记得把上面的"mybatis-plus-latest-version",使用时附上具体的版本号。和3.4.3一样,可以正常引入框架更多MP框架介绍,请访问其官网:https://baomidou.com/guide/①controller实现importcom.example.demo.model.User;importcom.example.demo.service.impl。UserServiceImpl;导入org.springframework.beans.factory.annotation.Autowired;导入org.springframework.web.bind.annotation.RequestMapping;导入org.springframework.web.bind.annotation.RestController;导入java.util.ArrayList;导入java.util.List;@RestController@RequestMapping("/u")publicclassUserController{@AutowiredprivateUserServiceImpluserService;/***批量插入(自定义)*/@RequestMapping("/mysavebatch")publicbooleanmySaveBatch(){Listlist=newArrayList<>();//要为(inti=0;i<1000;i++)添加的(用户)数据{Useruser=newUser();user.setName("测试:"+i);user.setPassword("123456");list.add(用户);}返回userService.saveBatchCustom(列表);}}②业务逻辑层实现importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl;导入com.example.demo.mapper.UserMapper;导入com.example.demo.model.User;导入com.example.demo.service.UserService;导入org.springframework.beans.factory。annotation.Autowired;importorg.springframework.stereotype.Service;importjava.util.List;@ServicepublicclassUserServiceImplextendsServiceImplimplementsUserService{@AutowiredprivateUserMapperuserMapper;publicbooleansaveBatchCustom(Listlist){returnuserMapper.saveBatchCustom(list);}}③数据持久层实现MapperpublicinterfaceUserMapperextendsBaseMapper{booleansaveBatchCustom(Listlist);}上面的代码实现后,我们就可以使用MP来实现数据的批量插入功能了,不过这个除了具体的实现代码外,我们还需要知道每个方法的执行效率,所以我们来写MP的测试代码MP性能测试Autowired;importorg.springframework.boot.test.context.SpringBootTest;importjava.util.ArrayList;importjava.util.List;@SpringBootTestclassUserControllerTest{//最大循环次数privatestaticfinalintMAXCOUNT=100000;@AutowiredprivateUserServiceImpl用户服务;/***MP批量插入*/@TestvoidsaveBatch(){longstime=System.currentTimeMillis();//统计开始时间Listlist=newArrayList<>();for(inti=0;iimplementsUserService{@AutowiredprivateUserMapperuserMapper;publicbooleansaveBatchByNative(Listlist){returnuserMapper.saveBatchByNative(list);}}②数据持久层扩展在UserMapper中添加saveBatchByNative方法,实现代码如下:.annotations.Mapper;importjava.util.List;@MapperpublicinterfaceUserMapperextendsBaseMapper{booleansaveBatchByNative(Listlist);}③添加UserMapper.xml创建UserMapper.xml文件,使用foreach标签拼接SQL。具体实现代码如下:INSERTINTO`USER`(`NAME`,`PASSWORD`)VALUES(#{item.name},#{item.password})经过以上步骤,我们原生的批量插入功能就差不多实现了,接下来我们使用单元测试来检验方法的有效性原生批量插入性能测试.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importjava.util.ArrayList;importjava.util.List;@SpringBootTestclassUserControllerTest{//最大循环次数privatestaticfinalintMAXCOUNT=100000;@AutowiredprivateUserServiceImpl用户服务;/***自己原生拼接SQL,批量插入*/@TestvoidsaveBatchByNative(){longstime=System.currentTimeMillis();//统计开始时间Listlist=newArrayList<>();for(inti=0;i