全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 8 分钟 ✍️ juanwangdev

ExecutorType 批量执行

MyBatis 提供三种执行器类型,合理选择执行器可以显著提升批量操作性能。本文对比三种执行器的差异,重点讲解 BATCH 批量执行器的使用。

三种 ExecutorType 对比

执行器内部行为适用场景性能
SIMPLE每次执行都创建新的 PreparedStatement默认,单次操作基准
REUSE复用 PreparedStatement,相同 SQL 不重复编译同一条 SQL 执行多次
BATCH将 SQL 加入批处理队列,统一 executeBatch()批量 INSERT/UPDATE

注意:默认执行器是 SIMPLE。可通过 defaultExecutorType 全局设置,或在获取 SqlSession 时单独指定。

SIMPLE 执行器

Java
// 默认使用 SIMPLE
SqlSession session = sqlSessionFactory.openSession();
for (int i = 0; i < 1000; i++) {
    mapper.insertUser(new User("user" + i, "user" + i + "@test.com"));
}
session.commit();
session.close();

SIMPLE 模式下,每次调用 insertUser 都会:

  1. 创建新的 PreparedStatement
  2. 设置参数
  3. 执行 executeUpdate()
  4. 释放资源

1000 次插入 = 1000 次网络往返 + 1000 次语句编译。

REUSE 执行器

Java
SqlSession session = sqlSessionFactory.openSession(ExecutorType.REUSE);
for (int i = 0; i < 1000; i++) {
    mapper.insertUser(new User("user" + i, "user" + i + "@test.com"));
}
session.commit();
session.close();

REUSE 模式下,相同的 SQL 语句只编译一次,复用 PreparedStatement。减少了编译开销,但每次执行仍然是独立的网络往返。

BATCH 执行器

基本用法

Java
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
    UserMapper mapper = session.getMapper(UserMapper.class);
    for (int i = 0; i < 1000; i++) {
        mapper.insertUser(new User("user" + i, "user" + i + "@test.com"));
    }
    session.commit();
} finally {
    session.close();
}

BATCH 模式下:

  1. mapper.insertUser() 不会立即发送 SQL 到数据库
  2. SQL 被加入批处理队列
  3. commit() 时统一调用 executeBatch()

1000 次插入 = 1 次网络往返 + 批量执行。

Mapper XML 配置

BATCH 模式下的 Mapper 写法与普通插入相同:

XML
<insert id="insertUser" parameterType="User">
    INSERT INTO user (username, email) VALUES (#{username}, #{email})
</insert>

注意:BATCH 模式使用的是 executeBatch(),不需要在 XML 中使用 foreach 拼接 SQL。

批量更新

Java
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
    UserMapper mapper = session.getMapper(UserMapper.class);
    for (User user : users) {
        mapper.updateUser(user);
    }
    session.commit();
} finally {
    session.close();
}

分批提交

当数据量极大时,避免在 BATCH 队列中堆积过多语句:

Java
public void batchInsertInChunks(List<User> users) {
    int batchSize = 500;
    SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
    try {
        UserMapper mapper = session.getMapper(UserMapper.class);
        for (int i = 0; i < users.size(); i++) {
            mapper.insertUser(users.get(i));
            // 每 500 条执行一次 commit
            if ((i + 1) % batchSize == 0) {
                session.commit();
                session.clearCache();
            }
        }
        // 提交剩余数据
        session.commit();
    } finally {
        session.close();
    }
}

注意:BATCH 模式下调用 commit() 后必须 clearCache() 清理缓存,避免内存泄漏。

全局配置 ExecutorType

MyBatis 配置文件

XML
<settings>
    <setting name="defaultExecutorType" value="BATCH"/>
</settings>

Spring 集成配置

XML
<bean id="batchSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory"/>
    <constructor-arg value="BATCH"/>
</bean>
Java
@Configuration
public class MyBatisConfig {
    @Bean
    public SqlSessionTemplate batchSqlSessionTemplate(SqlSessionFactory factory) {
        return new SqlSessionTemplate(factory, ExecutorType.BATCH);
    }
}

性能对比

场景SIMPLEREUSEBATCH
单次查询基准相同相同
同 SQL 查询 1000 次中(复用编译)不适用
1000 次 INSERT
1000 次 UPDATE
需要获取自增主键支持支持部分支持

注意:BATCH 模式下,MySQL 默认无法获取每条记录的自增主键,因为 executeBatch() 不返回 individual generated keys。如需要回填主键,考虑使用 foreach 方式。

BATCH 模式的限制

限制说明
无法获取自增主键MySQL BATCH 模式下 executeBatch() 不返回单条主键
动态 SQL 不生效BATCH 使用 PreparedStatement,<if><choose> 等动态标签无法在运行时判断
内存堆积不手动 commit 时,所有 SQL 在内存中排队,可能导致 OOM
无法立即看到结果SQL 在 commit() 时才真正执行,无法中途判断某条是否失败

要点总结

  • SIMPLE:每次执行创建新 PreparedStatement,适合单次操作
  • REUSE:复用 PreparedStatement,减少重复编译
  • BATCH:批处理模式,SQL 加入队列后统一 executeBatch(),批量写入性能最高
  • BATCH 模式注意每批 commit 后 clearCache(),避免内存泄漏
  • BATCH 模式无法获取自增主键,动态 SQL 不生效
  • 大批量数据分批提交,控制单次 BATCH 队列大小

📝 发现内容有误?点击此处直接编辑

← 上一篇 枚举类型处理
下一篇 → SQL 语句优化
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库