MyBatis 提供了 三种 Executor 执行器,用于执行 SQL 语句和处理结果集。它们是:
- SimpleExecutor(默认)
- ReuseExecutor
- BatchExecutor
🌟 1. SimpleExecutor(默认)
- 每次执行 SQL 语句时都会创建一个新的
Statement对象。 - 执行完成后立即关闭
Statement。 - 不会复用
Statement对象。
🔸 特点:
✅ 适合简单的、查询频率不高的操作。
✅ 不会占用数据库连接池资源。
❌ 性能较低,频繁创建和销毁 Statement,消耗资源。
示例:使用 SimpleExecutor
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.SIMPLE);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
sqlSession.commit();
sqlSession.close();
👉 每次 mapper.getUserById() 都会创建新的 Statement 对象,执行完毕后立即销毁。
🌟 2. ReuseExecutor
- 在执行 SQL 语句时,MyBatis 会尝试复用
Statement对象。 - 如果 SQL 语句与之前执行的相同,MyBatis 会复用已存在的
Statement,而不是重新创建。
🔸 特点:
✅ 适合执行频率较高的重复查询。
✅ 减少了 Statement 的创建和销毁,性能更高。
❌ 只对完全相同的 SQL 语句起作用(包括参数占位符结构)。
示例:使用 ReuseExecutor
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.getUserById(1);
User user2 = mapper.getUserById(2);
sqlSession.commit();
sqlSession.close();
👉 如果两个 getUserById 生成的 SQL 语句结构相同(即 "SELECT * FROM user WHERE id = ?"),会复用 Statement。
🌟 3. BatchExecutor
- 在执行 SQL 语句时,MyBatis 会将多个 SQL 语句缓存起来,最后一次性批量发送到数据库执行。
- 适合批量插入、批量更新等场景。
🔸 特点:
✅ 大幅减少与数据库的通信次数,提升性能。
✅ 适合批量操作场景,如导入数据或大批量更新。
❌ 需要手动提交(commit())。
❌ 在批处理失败时,可能会出现部分成功、部分失败的情况,事务处理复杂。
示例:使用 BatchExecutor
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.insertUser(new User(1, "Tom", 20));
mapper.insertUser(new User(2, "Jerry", 22));
mapper.insertUser(new User(3, "Spike", 25));
sqlSession.commit(); // 一次性提交
sqlSession.close();
👉 MyBatis 会将 3 条 INSERT 语句合并为一个批处理操作,最后通过 commit() 一次性发送到数据库。
🔥 执行器之间的区别总结
| 执行器类型 | 创建 Statement | 复用 Statement | 适用场景 | 性能 |
|---|---|---|---|---|
| SimpleExecutor | 每次执行创建新的 Statement | ❌ 不复用 | 普通的单次查询和操作 | 🚀🚀 |
| ReuseExecutor | 相同 SQL 语句复用 Statement | ✅ 复用相同 SQL 的 Statement | 高频率执行相同 SQL 的场景 | 🚀🚀🚀 |
| BatchExecutor | 批量创建和执行 Statement | ✅ 批量复用 | 批量插入、批量更新 | 🚀🚀🚀🚀 |
🎯 选择策略
✅ 如果查询或操作非常频繁且重复 → 选择 ReuseExecutor
✅ 如果是批量插入、批量更新等场景 → 选择 BatchExecutor
✅ 如果是普通场景,没有特殊性能要求 → 使用默认的 SimpleExecutor
MyBatis 中如何指定使用哪一种 Executor 执行器
对!这是因为在 MyBatis 中,Executor 的选择是由 MyBatis 框架自动处理的,所以在大多数情况下,你不需要直接在代码中指定 Executor 类型。
🌟 1. MyBatis 的默认行为
在没有明确配置的情况下,MyBatis 默认会使用 SimpleExecutor。
👉 默认配置来自于 mybatis-config.xml:
<configuration>
<settings>
<setting name="defaultExecutorType" value="SIMPLE"/>
</settings>
</configuration>
defaultExecutorType 取值可以是:
SIMPLE→ 使用SimpleExecutor(默认)REUSE→ 使用ReuseExecutorBATCH→ 使用BatchExecutor
🌟 2. 如何在代码中指定 Executor 类型
如果你需要显式指定 Executor 类型,可以通过 SqlSessionFactory.openSession() 方法设置:
🔸 使用 SIMPLE 执行器
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.SIMPLE);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
sqlSession.close();
🔸 使用 REUSE 执行器
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.getUserById(1);
User user2 = mapper.getUserById(2);
sqlSession.close();
🔸 使用 BATCH 执行器
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.insertUser(new User(1, "Tom", 20));
mapper.insertUser(new User(2, "Jerry", 22));
sqlSession.commit(); // 一次性提交
sqlSession.close();
🌟 3. 如果你用的是 Spring + MyBatis
在 Spring 配置中,也可以通过设置 defaultExecutorType 来配置全局 Executor 类型:
👉 在 application.properties 或 application.yml 文件中配置:
mybatis.configuration.default-executor-type=REUSE
✅ 为什么平时没见过?
- 大多数情况下,使用默认的
SIMPLE执行器已经够用了。 - MyBatis 会根据 SQL 类型和场景自动选择合适的执行器。
- 直接配置在
mybatis-config.xml或application.properties中,通常无需手动指定。
🚀 只有在性能优化或批量操作场景下,才需要手动指定 Executor! 😎
在spring 中默认是用的simple 如果为某几个单独设置batch 可以用以下方法
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = getUsers(); // 假设该方法返回需要更新的用户列表
for (User user : users) {
userMapper.updateStatusById(user.getId(), user.getStatus());
}
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
} finally {
sqlSession.close();
}