Mybatis-Plus批量插入应该怎么用(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Mybatis-Plus批量插入应该怎么用

mybatis-plus的 IService接口 默认提供 saveBatch批量插入,也是唯一一个默认批量插入,在数据量不是很大的情况下可以直接使用,但这种是一条一条执行的效率上会有一定的瓶颈,今天我们就来研究研究mybatis-plus中的批量插入。


1. 准备测试环境


新建一个测试表,用插入5000条数据来测试

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `user_name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  `account` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=60204 DEFAULT CHARSET=utf8;


pom依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
    </dependencies>


yml配置

spring:
  application:
    name: example-server
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/my_user?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: root
  main:
    allow-circular-references: true
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印


实体类

/**
 * @description: 默认驼峰转换
 * @author: yh
 * @date: 2022/8/29
 */
@Data
public class Users extends Model<Users> {
    /**
     * id自增
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private LocalDateTime createTime;
    private String userName;
    private Integer age;
    private String email;
    private String address;
    private String account;
    private String password;
}


UsersMapper

public interface UsersMapper extends BaseMapper<Users> {
}


UsersMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UsersMapper">
</mapper>


service接口

public interface UsersService extends IService<Users> {
}


service实现

@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService {
}


配置扫描

@MapperScan("com.example.mapper")
@SpringBootApplication
public class SpringExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringExampleApplication.class, args);
    }
}


环境准备完成。


2. saveBatch


@RequestMapping(value = "/api")
@RestController
@Slf4j
public class ExampleController {
    @Autowired
    private UsersService usersService;
    @RequestMapping(value = "/load", method = RequestMethod.GET)
    public void load() {
        List<Users> list = new ArrayList<>();
        for (int i = 0; i < 5000; i++) {
            Users users = new Users();
            users.setUserName("yy" + i);
            users.setAge(18);
            users.setEmail("123@qq.com");
            users.setAddress("临汾" + i);
            users.setAccount("account" + i);
            users.setPassword("password" + i);
            list.add(users);
        }
        long start = System.currentTimeMillis();
        usersService.saveBatch(list);
        long end = System.currentTimeMillis();
        System.out.println("5000条数据插入,耗时:" + (end - start));
    }
}

执行过程:

1673456926903.jpg

1673456934960.jpg

1673456941619.jpg

5000条数据被分成了5次执行,每次1000条,整体是一个事务

1673456950322.jpg

1673456956811.jpg

耗时:48.5秒


2.1 分析


点进saveBatch方法,看看内部是怎么实现的

1673456970035.jpg

注意看,方法有一个事务注解,说明插入整批数据会作为一个事务进行

1673456979862.jpg

默认1000条一次,怪不得执行时每隔1000条会处于一个准备执行状态,等待几秒后才会往下执行(这里等待的时间就是1000个单条的insert语句执行的时间)


再往下点是一个saveBatch接口,参数分别是插入的对象集合、插入批次数量也就是默认的1000

1673456986853.jpg

查看它的实现类

1673456993244.jpg

这里也有一个事务的注解,这是因为saveBatch是一个重载方法,插入的时候也可以指定插入批次数量调用

1673457000463.jpg

继续往下进入executeBatch

1673456802694.jpg

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
存储 SQL Java
MyBatis batchInsert 批量插入数据
MyBatis batchInsert 批量插入数据
112 0
|
7月前
|
SQL Java 数据库连接
Mybatis的批量插入Bigdecimal会丢失精度
Mybatis的批量插入Bigdecimal会丢失精度
507 0
|
7月前
|
SQL 存储 Kubernetes
Seata常见问题之mybatisplus的批量插入方法报SQL错误如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
258 0
|
SQL Java 数据库连接
MyBatis痛点验证,使用 foreach 批量插入慢?
MyBatis痛点验证,使用 foreach 批量插入慢?
419 0
|
7月前
|
存储 Java 数据库连接
MyBatis Plus中的批量插入:通过开启rewriteBatchedStatements=true
MyBatis Plus中的批量插入:通过开启rewriteBatchedStatements=true
718 0
|
7月前
|
Java 数据库连接 mybatis
mybatis 批量插入
mybatis 批量插入
41 0
|
SQL Java 数据库连接
如何使用Mybatis实现批量插入 ?
如何使用Mybatis实现批量插入 ?
86 0
|
小程序 Java 数据库连接
【实践】mybatis批量插入map
【实践】mybatis批量插入map
597 0
|
SQL 缓存 JavaScript
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 下
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 下
|
SQL Java 数据库连接
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 上
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 上