MyBatis的Executor执行器有哪几种类型?
MyBatis提供三种核心执行器:
Simple(默认,每次新建Statement)、Reuse(重用Statement)和Batch(批量处理)。此外,CachingExecutor作为装饰器,为它们提供二级缓存功能。
MyBatis 的 Executor(执行器)是其核心组件之一,负责 SQL 语句的生成、查询缓存的维护以及事务的管理。它直接与数据库进行交互。
MyBatis 主要提供了以下三种类型的 Executor 执行器:
SimpleExecutor(简单执行器)ReuseExecutor(重用执行器)BatchExecutor(批量执行器)
除此之外,还有一个特殊的执行器,它是一个装饰器:
CachingExecutor(缓存执行器)
下面我们来详细了解每一种。
三种基础执行器
1. SimpleExecutor (简单执行器)
这是 MyBatis 默认的执行器类型。
- 工作方式:每次执行
update或select操作时,它都会创建一个新的Statement或PreparedStatement对象。 - 优点:实现简单,逻辑清晰,每次都是全新的
Statement,不会有状态残留问题。 - 缺点:对于频繁执行相同 SQL 的场景,每次都需要创建和关闭
Statement对象,会带来一定的性能开销(虽然现代 JDBC 驱动对此有优化,但开销依然存在)。 - 适用场景:绝大多数常规场景。如果你没有特殊的性能要求或批量处理需求,使用默认的
SimpleExecutor就足够了。
2. ReuseExecutor (重用执行器)
这种执行器会重用 PreparedStatement 对象。
- 工作方式:它会将创建过的
PreparedStatement对象缓存起来(内部使用一个Map,Key 为 SQL 语句),当再次执行相同的 SQL 时,会直接从缓存中获取PreparedStatement对象,然后设置参数并执行,避免了重复创建和预编译的开销。 - 优点:对于频繁执行相同 SQL 的应用,可以显著提升性能,减少了 SQL 预编译和
Statement对象创建的开销。 - 缺点:当执行的 SQL 种类非常多时,缓存的
Statement也会非常多,可能会占用较多内存。 - 适用场景:适用于业务中存在大量重复 SQL 调用的高性能要求的场景。
3. BatchExecutor (批量执行器)
这种执行器专门用于执行批量更新操作(insert, update, delete)。
- 工作方式:当你调用
update方法时,它不会立即执行 SQL,而是将 SQL 添加到一个批处理列表中。当你手动调用flushStatements()方法或commit()事务时,它才会将缓存的 SQL 语句通过 JDBC 的addBatch()和executeBatch()方法一次性发送给数据库执行。 - 优点:大幅提升批量数据操作的性能,减少了网络交互次数和数据库的 I/O 操作。
- 缺点:在
flushStatements()被调用之前,你无法获取到数据库操作的结果(比如自增主键),因为它还没有真正执行。它对一级缓存的支持也有限,在批量操作期间,缓存会被清空。 - 适用场景:需要一次性插入、更新或删除大量数据的场景,例如数据迁移、批量导入等。
特殊的装饰器
CachingExecutor (缓存执行器)
这个执行器本身不直接执行 SQL,它是一个装饰器(Decorator),用来为其他执行器增加二级缓存的功能。
- 工作方式:当 MyBatis 配置了二级缓存后(在 Mapper XML 中添加
<cache/>标签),MyBatis 在创建 Executor 时会自动使用CachingExecutor来包装你配置的基础执行器(如SimpleExecutor)。 - 执行流程:
- 当一个查询请求过来时,
CachingExecutor首先会检查二级缓存中是否存在对应的结果。 - 如果二级缓存命中,则直接返回结果,不再执行后续操作。
- 如果二级缓存未命中,它会将请求委托(Delegate)给被它包装的那个基础执行器(例如
SimpleExecutor)。 - 基础执行器继续执行,它会先检查一级缓存,如果还没有,就查询数据库。
- 基础执行器从数据库获取到结果后,会将其存入一级缓存。
CachingExecutor在拿到基础执行器返回的结果后,会将这个结果存入二级缓存,然后再返回给调用者。
- 当一个查询请求过来时,
- 总结:
CachingExecutor的核心作用就是在基础执行器的功能之上,增加了二级缓存的读写逻辑。
如何配置和选择
你可以在 MyBatis 的全局配置文件 mybatis-config.xml 中设置默认的执行器类型:
xml
<settings>
<!-- 可选值为 SIMPLE, REUSE, BATCH -->
<setting name="defaultExecutorType" value="SIMPLE"/>
</settings>
也可以在代码中动态指定:
java
// 手动打开一个使用 BATCH 执行器的 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
// 手动打开一个使用 REUSE 执行器的 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE);
如果不指定,默认就是 ExecutorType.SIMPLE。
总结对比
| 执行器类型 | 主要特点 | 适用场景 | 备注 |
|---|---|---|---|
SimpleExecutor |
每次都创建新的 Statement |
大多数通用场景 | 默认配置,简单可靠 |
ReuseExecutor |
重用 PreparedStatement |
频繁执行重复 SQL 的高性能场景 | 减少了 SQL 预编译开销 |
BatchExecutor |
批量执行 insert/update/delete |
大批量数据导入、更新、删除 | 需要手动 flush 或 commit 才会执行,性能提升非常明显 |
CachingExecutor |
实现二级缓存,包装其他执行器 | 需要跨 SqlSession 共享缓存的场景 |
装饰器模式,当启用二级缓存时,MyBatis 会自动使用它进行包装 |