MyBatis Plus 批量数据插入功能,yyds!
最近 Review 小伙伴代码的时候,发现了一个小小的问题,小伙伴竟然在 for 循环中进行了 insert (插入)数据库的操作,这就会导致每次循环时都会进行连接、插入、断开连接的操作,从而导致一定的性能问题,简化后代码如下:
/**
* 插入操作
*/
@RequestMapping("/save")
public Object save() {
boolean flag = false; // 返回结果
// 待添加(用户)数据
for (int i = 0; i < 1000; i++) {
User user = new User();
user.setName("test:"+i);
user.setPassword("123456");
// 插入数据
flag = userService.save(user);
if(!flag) break;
}
return flag;
}
这样做并不会改变程序最终的执行结果,但会对程序的执行效率带来很大的影响,就好比你现在要从 A 地点送 10 件货到 B 地点,你可以选择 1 次送 1 件,送 10 次的方案;也可以选择 1 次送 10 件,送 1 次的方案,请问你会选择哪种?这就是多次循环插入和批量一次插入的问题。
PS:要插入的数据量越大,批量插入的时间(相比于循环多次插入来说)也越短、其优势也越大。
批量插入实现方案
本文我们使用 MyBatis-Plus(下文简称 MP)自带的 saveBatch 方法,来实现数据的批量插入功能,因为 MP 不是本文讨论的重点,所以这里咱们就不介绍了,如果有不熟悉的朋友可以去他的官方自行恶补:https://baomidou.com/guide/,咱们本文重点介绍一下 MP 实现批量插入的具体步骤。
1.引入 MP 框架
首先,打开您的 pom.xml 文件,在文件中添加以下内容:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>mybatis-plus-latest-version</version>
</dependency>
注意:mybatis-plus-latest-version 表示 MP 框架的最新版本号,可访问 https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter 查询最新版本号,但在使用的时候记得一定要将上面的 “mybatis-plus-latest-version”替换成换成具体的版本号,如 3.4.3 才能正常的引入框架。
2.创建数据库和表
此步骤可省略,主要用于本文功能的实现,创建数据库和数据表的脚本如下:
-- ----------------------------
-- 创建数据库
-- ----------------------------
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP DATABASE IF EXISTS `testdb`;
CREATE DATABASE `testdb`;
USE `testdb`;
-- ----------------------------
-- 创建 user 表
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`createtime` datetime NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- 添加测试数据
-- ----------------------------
INSERT INTO `user` VALUES (1, '赵云', '123456', '2021-09-10 18:11:16');
INSERT INTO `user` VALUES (2, '张飞', '123456', '2021-09-10 18:11:28');
INSERT INTO `user` VALUES (3, '关羽', '123456', '2021-09-10 18:11:34');
INSERT INTO `user` VALUES (4, '刘备', '123456', '2021-09-10 18:11:41');
INSERT INTO `user` VALUES (5, '曹操', '123456', '2021-09-10 18:12:02');
SET FOREIGN_KEY_CHECKS = 1;
3.具体代码实现(重点)
① 实体类
先来创建数据库所对应的 User 实体类:
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
@Getter
@Setter
public class User {
private int id;
private String name;
private String password;
private Date createtime;
}
② Controller 层代码
本文的核心是使用 MP 框架中,IService 类提供的 saveBatch 方法,来实现批量数据的插入功能,对应在 Controller 中的实现代码如下:
import com.example.demo.model.User;
import com.example.demo.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/u")
public class UserController {
@Autowired
private UserServiceImpl userService;
/**
* MP 批量插入
*/
@RequestMapping("/savebatch")
public boolean saveBatch() {
List<User> list = new ArrayList<>();
// 待添加(用户)数据
for (int i = 0; i < 1000; i++) {
User user = new User();
user.setName("test:"+i);
user.setPassword("123456");
list.add(user);
}
// 批量插入
return userService.saveBatch(list);
}
}
③ Service 层代码(重点)
接下来,我们要创建一个 UserService 接口,继承 MP 框架中的 IService 接口,实现代码如下:
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.model.User;
public interface UserService extends IService<User> {
}
然后再创建一个 UserService 的实现类:
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User>
implements UserService {
}
PS:注意 UserServiceImpl 必须要继承 MP 框架中的 ServiceImpl,不然要重写很多方法。
④ Mapper 层代码
Mapper 层的实现相对来说就比较简单了,只需要创建一个 Mapper 类继承 MP 框架中的 BaseMapper 类即可,实现代码如下:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.model.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User>{
}
PS:BaseMapper 提供了对某个对象(类)最基础的 CRUD 操作。
总结
本文我们介绍了 MP(MyBatis Plus)中实现批量插入的具体实现步骤,它的核心是通过调用 MP 中 IService 提供的 saveBatch 方法来完成的,但如果项目中没有引入 MP 框架该如何处理?是不是使用了 MP 就可以躺平了呢?不着急,下篇我们再聊批量插入的另一种方式(原生批量插入的实现方式),以及二者之间的优缺点分析。
关注公号「Java中文社群」查看更多 MyBatis 和 Spring Boot 的系列文章。
MyBatis Plus 批量数据插入功能,yyds!的更多相关文章
- yii批量数据插入
yii框架批量插入数据有两种方法,第一种是循环多次插入和一次批量插入,第一种方法要注意插入数据中间有一次数据插入失败要注意回滚事务 循环插入数据 第一种方法 $model = new User(); ...
- EF结合SqlBulkCopy实现高效的批量数据插入 |EF插件EntityFramework.Extended实现批量更新和删除
原文链接:http://blog.csdn.net/fanbin168/article/details/51485969 批量插入 (17597条数据批量插入耗时1.7秒) using Sys ...
- [oracle/java/sql]用于上十万批量数据插入Oracle表的Java程序
程序下载:https://files.cnblogs.com/files/xiandedanteng/LeftInnerNotExist20191222.rar 原理:Oracle的Insert al ...
- 原创 SqlParameter 事务 批量数据插入
不错,很好,以后防注入批量事务提交虽然麻烦点研究了几个小时,但不会是问题了 SqlCommand cmd; HelpSqlServer helps = new HelpSqlServer(); //定 ...
- 使用SqlBulkCopy进行批量数据插入
Dim dt As DataTable = New DataTable() dt.Columns.Add("DtCostProductRuleGUID", GetType(Guid ...
- MyBatis中批量插入数据对插入记录数的限制
<基于Mybatis框架的批量数据插入的性能问题的探讨>(作者:魏静敏 刘欢杰 来源:<计算机光盘软件与应用> 2013 年第 19 期)中提到批量插入的记录数不能超过1000 ...
- KingbaseES批量数据加载的实践技巧
有时,KingbaseES数据库需要在单个或最少的步骤中导入大量数据,这通常称为批量数据导入.其中数据源通常是一个或多个大文件,这个过程有时可能非常慢. 造成性能不佳的原因有很多:索引.触发器.外键. ...
- myBatis获取批量插入数据的主键id
在myBatis中获取刚刚插入的数据的主键id是比较容易的 , 一般来说下面的一句话就可以搞定了 , 网上也有很多相关资料去查. @Options(useGeneratedKeys = true, k ...
- mybatis foreach批量插入数据:Oracle与MySQL区别
mybatis foreach批量插入数据:Oracle与MySQL不同点: 主要不同点在于foreach标签内separator属性的设置问题: separator设置为","分 ...
随机推荐
- 题解 P3322 [SDOI2015]排序
题解 仔细审题,我们会发现 小 \(A\) 认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同). 所以,对于一种操作,不管是交换哪两段,都算作同一种操作,只会 ...
- Struts2之国际化
时间:2017-1-11 11:12 --国际化Struts2已经对国际化进行了封装,我们只需要根据其提供的API进行访问即可.要使用国际化的Action必须继承ActionSupport.1.什么是 ...
- 微信小程序学习笔记四 页面的生命周期
1. 生命周期 1.1 对应阶段说明 onLOad(Object query) 1.1 页面加载时触发, 一个页面只会调用一次, 可以在 onLoad的参数中获取打开当前页面路径中的参数 1.2 参数 ...
- 《redis 5设计与源码分析》:第二章 简单动态字符串
介绍 简单动态字符串(Simple Dynamic Strings, SDS)是Redis的基本数据结构之一,用于存储字符串和整型数据.它的特点是:方便扩容.二进制安全. 二进制安全 在C语言中,用& ...
- docker PXC MYSQL集群节点启动失败/节点顺序消失/只剩一个节点存在问题的解决
转载于:https://my.oschina.net/u/4884318/blog/4908669 大牛 佩服此人 截取本人遇到的问题: "error:0407008A:rsa routin ...
- Java全栈方向学习路线
前端方向 前端基础 HTML --> https://www.w3school.com.cn/html/index.asp CSS --> https://www.w3school.com ...
- IP掩码的作用
IP地址&IP掩码==网段,即,与上掩码后相同的IP属于同一网段.
- CSS3 animaion 和 transition 比较
animation是CSS3的动画属性,可以设置以下六种属性. transition是CSS3的过度属性,可以设置以下四种属性. 从属性上分析,animation可以设定循环次数. 其次,两者的触发条 ...
- 从零开始实现简单 RPC 框架 9:网络通信之心跳与重连机制
一.心跳 什么是心跳 在 TPC 中,客户端和服务端建立连接之后,需要定期发送数据包,来通知对方自己还在线,以确保 TPC 连接的有效性.如果一个连接长时间没有心跳,需要及时断开,否则服务端会维护很多 ...
- go 发送post请求(键值对、上传文件、上传zip)
一.post请求的Content-Type为键值对 1.PostForm方式 package main import ( "net/http" "net/url" ...