executor

57 阅读3分钟

一、Executor 的核心设计:模板方法模式

模板方法模式BaseExecutor 中的应用:

  • 抽象流程定义BaseExecutor 作为所有 Executor 的抽象基类,定义了 SQL 执行的通用流程(如事务提交、缓存管理、异常回滚等),具体操作(如 doQuerydoUpdate)由子类实现。

  • 关键方法

    • query():执行查询的公共逻辑(如缓存检查、结果映射)。
    • update():执行更新的公共逻辑(如清空缓存)。
  • 子类职责:子类(如 SimpleExecutor)只需实现 doQuerydoUpdate 等具体操作,无需重复处理通用逻辑。


二、Executor 的具体实现

1. BaseExecutor
  • 角色:所有 Executor 的基类,提供以下功能:

    • 一级缓存管理:通过 PerpetualCache 实现 SqlSession 级别的缓存。
    • 事务管理:调用 Transaction 对象提交或回滚事务。
    • 延迟加载:支持关联对象的延迟加载(需配置 <lazyLoadingEnabled>)。
2. SimpleExecutor
  • 特点

    • 默认执行器,每次执行 SQL 时创建新的 Statement,执行后立即关闭。
    • 适用于单次查询或更新操作。
  • 源码示例

    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 添加二级缓存功能。

  • 工作流程

    1. 查询时优先从二级缓存获取数据。
    2. 缓存未命中时委托底层 Executor 执行查询,并将结果存入缓存。
    3. 更新操作清空相关缓存。
  • 启用条件:在 Mapper XML 中配置 <cache/> 标签。


三、Executor 的生命周期

Executor 的生命周期与 SqlSession 紧密绑定,分为以下阶段:

1. 创建阶段
  • 触发时机:通过 SqlSessionFactory.openSession() 创建 SqlSession 时,根据配置的 executorTypeSIMPLEREUSEBATCH)生成对应的 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,避免连接泄漏。