源本科技 | 码上会

批量操作

2026/04/02
0
0

引言

批量操作是通过一次数据库交互执行多条 SQL 的数据处理方式,核心价值是减少应用与数据库的网络 IO 次数,大幅提升大数据量的写入 / 更新 / 删除性能。

MyBatis Plus 提供两套批量操作方案

  1. 基础批量saveBatch/updateBatchById(低版本支持,底层循环单条执行)

  2. 高级批量MybatisBatch/MybatisBatchUtils3.5.4+ 版本支持,底层执行真正的批量 SQL,性能最优)


优势

  1. 极致性能:真正的批量 SQL 执行,性能是基础批量的 5~10 倍

  2. 功能全面:支持插入、更新、删除、自定义 Mapper 方法、批量 saveOrUpdate

  3. 灵活兼容:支持 Spring/ 非 Spring 环境,兼容所有数据库

  4. 结果可查:返回 BatchResult 批量执行结果,便于业务校验

  5. 事务安全:完美支持 Spring 事务管理

  6. 无侵入:无需修改原有 Mapper/Service 代码


版本要求

  1. 核心版本:MyBatis Plus 3.5.4 +

  2. 必须注入:SqlSessionFactory(Spring 容器自动管理)

  3. 基础依赖:mybatis-plus-boot-starter

  4. 数据库:支持 MySQL、Oracle、PostgreSQL 等主流数据库


核心组件

高级批量操作基于 3 个核心类实现,位于包 com.baomidou.mybatisplus.core.batch

组件

作用

MybatisBatch<T>

批量操作核心类,绑定 SqlSessionFactory + 批量数据

MybatisBatch.Method<T>

绑定执行的 Mapper 类与方法(insert/update/delete/ 自定义)

BatchResult

批量执行结果封装,记录每条 SQL 的执行情况

MybatisBatchUtils

静态工具类,简化批量调用(推荐使用)


核心 API

执行方法

方法

适用场景

execute()

批量插入、更新、删除(纯新增 / 纯修改)

saveOrUpdate()

批量保存或更新(存在则更新,不存在则插入)

常用 Mapper 方法

// 批量插入
method.insert()
// 根据 ID 批量更新
method.updateById()
// 自定义 Mapper 方法
method.get("自定义方法名", 参数转换器)

结果返回

List<BatchResult>:按 SQL 类型分组返回执行结果,可统计成功条数。


使用步骤

  1. 注入 SqlSessionFactory

  2. 准备批量数据列表

  3. 通过 MybatisBatchUtils 静态调用执行批量操作

  4. (可选)添加事务控制


实战示例

前置准备

@Autowired
private SqlSessionFactory sqlSessionFactory;

示例 1

静态工具类批量插入(推荐)

最简写法,无需手动创建对象

// 1. 准备 1000 条测试数据
List<H2User> userList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
    userList.add(new H2User("批量用户 " + i));
}

// 2. 静态工具类执行批量插入
List<BatchResult> results = MybatisBatchUtils.execute(
        sqlSessionFactory,
        userList,
        new MybatisBatch.Method<>(H2UserMapper.class).insert()
);

示例 2

非实体类型批量插入

原始数据为 ID/ 普通类型,自动转换为实体

List<Long> idList = Arrays.asList(1001L, 1002L, 1003L);

MybatisBatchUtils.execute(
        sqlSessionFactory,
        idList,
        new MybatisBatch.Method<>(H2UserMapper.class).insert(id -> {
            // 数据类型转换:Long → H2User
            H2User user = new H2User();
            user.setId(id);
            user.setName("转换用户 " + id);
            return user;
        })
);

示例 3

根据 ID 批量更新

List<H2User> updateList = new ArrayList<>();
H2User user1 = new H2User(1L, "更新名称 1");
H2User user2 = new H2User(2L, "更新名称 2");
updateList.add(user1);
updateList.add(user2);

MybatisBatchUtils.execute(
        sqlSessionFactory,
        updateList,
        new MybatisBatch.Method<>(H2UserMapper.class).updateById()
);

示例 4

自定义 Mapper 方法批量执行

支持注解 /XML 自定义 SQL,无侵入

// Mapper 层自定义方法
@Insert("INSERT INTO h2_user(name, age) VALUES(#{name}, #{age})")
int insertUser(H2User user);

// 批量执行自定义方法
MybatisBatchUtils.execute(
        sqlSessionFactory,
        userList,
        new MybatisBatch.Method<>(H2UserMapper.class).get("insertUser")
);

示例 5

批量 saveOrUpdate(存在更新,不存在插入)

MybatisBatchUtils.saveOrUpdate(
        sqlSessionFactory,
        userList,
        // 插入方法
        new MybatisBatch.Method<>(H2UserMapper.class).insert(),
        // 判断逻辑:ID 不存在则插入
        (sqlSession, user) -> userMapper.selectById(user.getId()) == null,
        // 更新方法
        new MybatisBatch.Method<>(H2UserMapper.class).updateById()
);

事务管理

批量操作必须开启事务,保证数据一致性,Spring 环境推荐 TransactionTemplate

@Autowired
private TransactionTemplate transactionTemplate;

// 事务中执行批量操作
List<BatchResult> results = transactionTemplate.execute(status -> {
    try {
        return MybatisBatchUtils.execute(sqlSessionFactory, userList,
                new MybatisBatch.Method<>(H2UserMapper.class).insert());
    } catch (Exception e) {
        // 异常回滚
        status.setRollbackOnly();
        throw new RuntimeException("批量插入失败", e);
    }
});

性能对比

方案

底层实现

性能

适用版本

推荐指数

基础批量(saveBatch)

循环单条执行

全版本

⭐⭐

高级批量(MybatisBatch)

原生批量 SQL

3.5.4+

⭐⭐⭐⭐⭐


极致性能优化

  1. 控制批次大小 每批次数据量建议 500~1000 条,避免数据包过大

  2. 关闭无需的特性 大数据量关闭自动填充、逻辑删除校验(非必要)

  3. 只读事务 仅查询场景使用 @Transactional(readOnly = true)

  4. 数据库级优化 超大数据量(千万级)使用数据库原生 LOAD DATA(MySQL):

LOAD DATA INFILE '/path/data.csv'
INTO TABLE h2_user
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;

注意事项

  1. 严禁循环调用批量方法 循环中频繁获取数据库连接,会导致性能急剧下降

  2. SqlSessionFactory 必须注入 非 Spring 环境需手动初始化 MyBatis 并获取 SqlSessionFactory

  3. 异常处理 批量执行抛出 PersistenceException,需统一捕获

  4. 跨 SqlSession 问题 saveOrUpdate 跨会话时,需手动查询数据状态,避免缓存问题

  5. 不支持分页 批量操作仅用于全量数据处理,不结合分页使用

  6. 基础批量的坑 低版本 saveBatch 并非真正批量,大数据量严禁使用


总结

  1. MyBatis Plus 3.5.4+ 提供的 MybatisBatch真正高性能批量操作方案

  2. 核心价值:减少网络 IO,百万级数据处理性能提升 10 倍

  3. 支持场景:批量插入、更新、删除、自定义方法、saveOrUpdate

  4. 必须搭配事务使用,保证数据安全

  5. 静态工具类 MybatisBatchUtils 是企业开发首选,代码极简、易维护

  6. 大数据量优先选择高级批量,超大数据量使用数据库原生 LOAD DATA