【MyBatis-Plus】之批量插入

2023-11-13

一、应用情景介绍


在实际的项目开发过程中,常常遇到批量保存数据的场景,当数据量比较少,比如只有几条数据的情况下,我们可以使用 for 循环来 insert 数据,但如果数据量比较多的情况下就不行,特别是并发的情况下,因为这样会增加数据库的负担。

我们通过查看 mybatis-plus 源码发现,mybatis-plusIService API 接口提供了批量插入的接口:

public interface IService<T> {
    ......
    /**
     * 插入(批量)
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean saveBatch(Collection<T> entityList) {
        return saveBatch(entityList, DEFAULT_BATCH_SIZE);
    }
    ......

查看该批量插入的实现方法源码:

public boolean saveBatch(Collection<T> entityList, int batchSize) {
    String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
    try (SqlSession batchSqlSession = sqlSessionBatch()) {
        int i = 0;
        // 在for循环中循环调用insert
        for (T anEntityList : entityList) {
            batchSqlSession.insert(sqlStatement, anEntityList);
            if (i >= 1 && i % batchSize == 0) {
                batchSqlSession.flushStatements();
            }
            i++;
        }
        batchSqlSession.flushStatements();
    }
    return true;
}

从源码可以看到,所谓的批量插入就是一个 for 循环插入,很明显,这不是我们想要结果。而当我们继续阅读 mybatis-plus 的源码可以发现,在 com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn 包中已经为我们实现了真正意义上的批量插入方法,这里就不贴实现的源码了,有兴趣的可以去看看。

因此,我们需要做的就是生效该批量了插入方法,从而可以让我们通过 Mapper 来调用它。


二、实现批量插入


1、引入依赖

<!-- mybatis plus 与 springboot 整合的依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>

<!-- mybatis plus extension 包含了 mybatis plus core -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-extension</artifactId>
    <version>3.4.0</version>
</dependency>

2、编写自定义SQL注入类

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;

import java.util.List;

/**
 * @Description: 支持自定义SQL注入方法
 * @author 王廷云
 * @date 2021/9/8 16:58
 */
public class CustomSqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        // 获取父类SQL注入方法列表
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 将批量插入方法添加进去
        methodList.add(new InsertBatchSomeColumn());
        return methodList;
    }

}

在这里,我们先获取默认的 SQL 注入方法列表,然后再讲批量插入方法添加进去。默认的方法列表有哪些呢,下面是我通过断点调试的截图:
在这里插入图片描述
可以看到,默认就是我们常用的 InsertDeleteUpdateSelectOne 等方法。

3、将该类注入到 Bean 中

@Configuration
public class MybatisPlusConfig {

    @Bean
    public CustomSqlInjector customSqlInjector() {
        return new CustomSqlInjector();
    }

}

4、将批量插入方法扩展进 BaseMapper 中

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.Collection;

/**
 * 自定义Mapper,添加批量插入接口
 */
public interface CustomMapper<T> extends BaseMapper<T> {

    /**
     * 批量插入
     * @param entityList 实体列表
     * @return 影响行数
     */
    Integer insertBatchSomeColumn(Collection<T> entityList);

}

注意: 不要忘记在启动类 Application 中添加 @MapperScan(basePackages = "xxx.xxx") 使该 Mapper 被扫描到。

5、测试验证

1)在数据库中创建用户表

CREATE TABLE `user`(
	`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '主键',
	`name` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '姓名',
	`age` INT(4) NOT NULL DEFAULT 0 COMMENT '年龄',
	PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

2)编写实体类

@Data
@Accessors(chain = true)
@TableName("user")
public class User {

    @TableId(type = IdType.AUTO)
    private Integer id;

    @TableField(value = "name")
    private String name;

    @TableField(value = "age")
    private Integer age;

}

3)编写 Mapper 接口

public interface UserMapper extends CustomMapper<User> {
}

4)编写 DAO 层

@Repository
public class UserDao {

    @Autowired
    private UserMapper userMapper;

    public void insertBatch(List<User> userList) {
        userMapper.insertBatchSomeColumn(userList);
    }

}

5)编写 Service 层

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    /**
     * 批量插入用户
     */
    public void insertUserBatch() {
        List<User> list = new ArrayList<>();
        list.add(new User().setName("Andy").setAge(18));
        list.add(new User().setName("wang").setAge(20));
        userDao.insertBatch(list);
    }

}

6)测试

当调用 UserServiceinsertUserBatch() 方法时,就会触发批量插入,查看 SQL 输出日志:

JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2458318b] will not be managed by Spring
==>  Preparing: INSERT INTO user (name,age) VALUES (?,?) , (?,?)
==>  Parameters: Andy(String), 18(Integer), wang(String), 20(Integer)
<==  Updates: 2

可以看到,批量插入的 SQL 是真正意义上的批量插入。

注意: 查看 Mybatis-plusSQL 输出日志需要添加配置:

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【MyBatis-Plus】之批量插入 的相关文章

随机推荐

  • 认知与思考-190820

    首先我觉得人应该读自己能驾驭的书 或者说自己的人格坚固 道家讲道心 佛家讲慧根 其实就是自己的本心不为所动 如果能 读各种书只会增加你处事能力和分辨万物的能力 你是主体 知识只是你解决方式的手段 向阳而生 你要知道 世间万物本就存在 你读不
  • 【第60篇】多目标跟踪:文献综述

    文章目录 摘要 1 简介 1 1 与其他相关综述的区别 1 2 贡献 1 3 综述的结构 1 4 外延 2 MOT问题 2 1 问题公式化 2 2 MOT的分类 2 2 1 初始化方法 2 2 2 处理方式 2 2 3 输出类型 2 2 4
  • 3 Decomposition Methods

    分解方法是解决问题的一般方法 其将问题分解为更小的问题并且并行地或者顺序地解决每个更小的问题 当采用顺序的方式时 优点是问题的复杂性呈超线性增长 more than linearly 如果问题在单步操作中分解有效 那么我称该问题为 块 可分
  • 数据分析36计(20):优化新财年广告预算,乘法营销组合模型的Python实现

    目录 文末附数据和代码 1 简介 如果你有做过FB广告投放 对 ROI 和 ROAS 这两个词一定不陌生 因为招聘的时候肯定会问你两个问题 你接触过多大的盘子 即花过多少预算 你的ROI一般是多少 广告客户使用营销组合模型 MMM 来衡量其
  • 运算放大器---增益带宽积(GBW)

    增益带宽积 GBW 电压反馈型运算放大器的增益带宽决定了其在某项应用中的有效带宽 将增益带宽除以应用中的实际闭环增益 便可大致估算出最大可用带宽 对于电压反馈放大器 增益带宽积 GBW 是衡定的常数 很多的应用都得益于所选择的更大带宽 转换
  • 电路板上为何要有孔洞?何谓PTH/NPTH/vias(导通孔)

    http www greattong com archives view 443 1 html 电路板上为何要有孔洞 何谓PTH NPTH vias 导通孔 发布时间 2016 07 13 09 39 阅读 3613 来源 技术文章 责任编
  • Vim插件合集 (打造你的专属炫酷IDE)

    Vim插件合集 本篇 主要来介绍一下 如何使用 Vim的插件功能 去把Vim打造成 炫酷 多功能的IDE 让你可以用Vim编写Python Go 等等 而不用繁重的 Pycharm 等高级Ide 效果图 前置知识 vim映射 就是映射你自己
  • 阿里全球数学竞赛最强10人名单出炉:仅1人来自北大,但北大是最大赢家

    鱼羊 杨净 发自 凹非寺量子位 报道 公众号 QbitAI 又一次的全球数学狂欢 落下帷幕 经过4个月的赛程 第三届阿里巴巴全球数学竞赛结果新鲜出炉 52850名参赛选手中 最终有70人获奖 99 9 的人无缘奖牌 北大成最大赢家 不仅有2
  • react 中使用递归和 TS 泛型来处理树形数据

    解决场景 使用递归把树形数据中的 children 替换成 children undefind page1 ts import formatTree from formatData ts const treeLists name paren
  • 线性稳压电路

    如图为串联式稳压电路 之所以叫串联式是因为T管与负载RL串联 工作原理 1 稳压管 Dz 与限流电阻R串联 得到基准电压 2 与组成反馈网络 得到反馈电压 3 净输入量的变化 引起的变化 4 的变化使调整管T的c e 极间的电压降变化 从而
  • Linux文件目录类(常用指令)

    文件目录类 cd指令 基本语法 cd 参数 功能描述 切换到指定目录 cd 或者cd 回到自己的家目录 cd 回到当前目录的上一目录 绝对路径和相对路径 绝对路径 目标文件在硬盘上的真实路径 最精确路径 从根目录开始的 相对路径 相对于当前
  • 将程序打成jar包后运行mapReduce时出现File does not exit: hdfs://localhost....jar

    出现的问题 解决方法 直接向报错路径添加报错提示的文件
  • Installation failed with message Invalid File:

    最近在studio 在安装apk的时候遇到了这么个问题 他说我之前已经有安装版本了 但是这个apk却是我第一次安装 怎么回事 之前遇到过一次 自己不知道怎么解决了 当时忘记记录下来现在记录下来 给自己和后面遇到的朋友 提供一个快速的解决办法
  • 圣路易斯大学计算机科学,圣路易斯华盛顿大学计算机科学专业

    圣路易斯华盛顿大学计算机科学与工程系申请要求需要托福 接受雅思 需要GRE GPA 3 0 学费 47 300 年 春季 秋季入学 截止日 1月15日 PhD 3月1日 MS M Eng 圣路易斯华盛顿大学计算机科学与工程系课程 网络物理系
  • 说说你对Vue生命周期的理解?

    一 生命周期是什么 生命周期 Life Cycle 的概念应用很广泛 特别是在政治 经济 环境 技术 社会等诸多领域经常出现 其基本涵义可以通俗地理解为 从摇篮到坟墓 Cradle to Grave 的整个过程 在Vue中实例从创建到销毁的
  • OpenCV InputArray和OutputArray

    InputArray这个接口类可以是Mat Mat
  • Attention注意力机制--原理与应用

    Attention注意力机制 原理与应用 注意力机制即Attention mechanism在序列学习任务上具有巨大的提升作用 在编解码器框架内 通过在编码段加入A模型 对源数据序列进行数据加权变换 或者在解码端引入A模型 对目标数据进行加
  • 那些会阻碍程序员成长的细节[3]

    前两篇文间几乎是想到那里就写到那里 没有分门别类的加以阐述 本篇延续以上两篇文章的思路 在之前的基础再追加 没有看过前两篇文章的同学可通过这两个链接回顾一下 那些会阻碍程序员成长的细节 一 那些会阻碍程序员成长的细节 二 不能主动推动事物前
  • Halcon标定板标定

    halcon标定有自己的标定助手可以演示 不过拿到VS里面却不是很适用 尤其是关于畸变矫正和透视矫正算子的解释也没有 下面两个算子set origin pose gen image to world plane map关键参数怎么计算也没有
  • 【MyBatis-Plus】之批量插入

    一 应用情景介绍 在实际的项目开发过程中 常常遇到批量保存数据的场景 当数据量比较少 比如只有几条数据的情况下 我们可以使用 for 循环来 insert 数据 但如果数据量比较多的情况下就不行 特别是并发的情况下 因为这样会增加数据库的负