一、Executor 的核心设计:模板方法模式
模板方法模式 在 BaseExecutor 中的应用:
-
抽象流程定义:
BaseExecutor作为所有 Executor 的抽象基类,定义了 SQL 执行的通用流程(如事务提交、缓存管理、异常回滚等),具体操作(如doQuery、doUpdate)由子类实现。 -
关键方法:
query():执行查询的公共逻辑(如缓存检查、结果映射)。update():执行更新的公共逻辑(如清空缓存)。
-
子类职责:子类(如
SimpleExecutor)只需实现doQuery和doUpdate等具体操作,无需重复处理通用逻辑。
二、Executor 的具体实现
1. BaseExecutor
-
角色:所有 Executor 的基类,提供以下功能:
- 一级缓存管理:通过
PerpetualCache实现SqlSession级别的缓存。 - 事务管理:调用
Transaction对象提交或回滚事务。 - 延迟加载:支持关联对象的延迟加载(需配置
<lazyLoadingEnabled>)。
- 一级缓存管理:通过
2. SimpleExecutor
-
特点:
- 默认执行器,每次执行 SQL 时创建新的
Statement,执行后立即关闭。 - 适用于单次查询或更新操作。
- 默认执行器,每次执行 SQL 时创建新的
-
源码示例:
public class SimpleExecutor extends BaseExecutor { @Override public <E> List<E> doQuery(...) { Statement stmt = prepareStatement(handler, ...); return handler.query(stmt, resultHandler); } }
3. ReuseExecutor
-
特点:
- 复用
PreparedStatement:缓存相同 SQL 的PreparedStatement对象,减少重复编译开销。 - 适用于高频重复 SQL 执行(如循环调用同一查询)。
- 复用
-
缓存逻辑:
public class ReuseExecutor extends BaseExecutor { private final Map<String, PreparedStatement> statementMap = new HashMap<>(); // 执行时优先从缓存获取 PreparedStatement }
4. BatchExecutor
-
特点:
- 批量模式:将多个更新操作缓存后一次性提交,减少数据库交互次数。
- 适用于批量插入、更新或删除。
-
使用示例:
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper = session.getMapper(UserMapper.class); for (User user : userList) { mapper.insertUser(user); // 添加至批处理队列 } session.commit(); // 一次性提交 }
5. CachingExecutor
-
角色:装饰器模式实现,为其他 Executor 添加二级缓存功能。
-
工作流程:
- 查询时优先从二级缓存获取数据。
- 缓存未命中时委托底层 Executor 执行查询,并将结果存入缓存。
- 更新操作清空相关缓存。
-
启用条件:在 Mapper XML 中配置
<cache/>标签。
三、Executor 的生命周期
Executor 的生命周期与 SqlSession 紧密绑定,分为以下阶段:
1. 创建阶段
-
触发时机:通过
SqlSessionFactory.openSession()创建SqlSession时,根据配置的executorType(SIMPLE、REUSE、BATCH)生成对应的 Executor 实例。 -
源码逻辑:
public class DefaultSqlSessionFactory implements SqlSessionFactory { public SqlSession openSession(ExecutorType execType) { Executor executor = configuration.newExecutor(transaction, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } }
2. 运行阶段
-
职责:
- 执行 SQL 语句(查询、更新)。
- 管理一级缓存和事务(如提交、回滚)。
-
线程安全性:Executor 非线程安全,需确保每个线程使用独立的
SqlSession。
3. 销毁阶段
-
触发时机:调用
SqlSession.close()时,Executor 会执行以下操作:- 提交未完成的事务(若配置为自动提交)。
- 关闭所有未关闭的
Statement和数据库连接。 - 清空一级缓存。
-
资源释放:
public void close() { executor.close(isCommitOrRollbackRequired(false)); }
四、总结
-
核心设计:基于模板方法模式,
BaseExecutor定义公共逻辑,子类实现具体 SQL 执行策略。 -
执行器类型:
- SimpleExecutor:简单场景。
- ReuseExecutor:高频重复 SQL。
- BatchExecutor:批量操作。
- CachingExecutor:二级缓存支持。
-
生命周期:与
SqlSession同生共死,从创建到销毁全程管理数据库操作和资源释放。
最佳实践:
- 批量操作显式使用
BatchExecutor以提升性能。 - 长事务场景及时关闭
SqlSession,避免连接泄漏。