MyBatis源码-解读Executor的三个实现类之BatchExecutor(批处理执行器)

2021-08-17 15:24:29 浏览数 (1)

Pre

MyBatis源码-深入理解MyBatis Executor的设计思想

工程部分见 MyBatis源码- SqlSession门面模式 & selectList 源码解析

实际中,我们都是面向SqlSession编程的,不会直接调用Executor来执行业务逻辑,这里我们仅仅是为了深入了解下Executor体系架构才这么搞的,切记。


Executor 执行器


接口继承关系

这里我们重点看下Executor的 三个实现子类。

分别是:SimpleExecutor(简单执行器)、ReuseExecutor(重用执行器)、BatchExecutor(批处理执行器)。


BatchExecutor(重用执行器)

BatchExecutor 仅对修改操作(包括删除)有效哈 ,对 select操作是不起作用。

BatchExecutor 主要是用于做批量更新操作的 ,底层会调用Statement的 executeBatch()方法实现批量操作

入门小demo

代码语言:javascript复制
 @Test
    public void testBatchExecutor() throws SQLException {
        // 通过factory.openSession().getConnection()实例化JdbcTransaction ,用于构建BatchExecutor
        jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection());

        // 实例化BatchExecutor
        BatchExecutor executor = new BatchExecutor(configuration, jdbcTransaction);

        // 映射SQL
        ms = configuration.getMappedStatement("com.artisan.UserMapper.updateById");

        Map map = new HashMap();
        map.put("arg0",1);
        map.put("arg1","222");

        // 调用doUpdate
        executor.doUpdate(ms,map);
        executor.doUpdate(ms,map);

        // 刷新
        executor.doFlushStatements(false);
        // 提交  否则不生效
        executor.commit(true);
     
    }

源码

currentSql 全局变量, 非线程安全

statementList 缓存 statement batchResultList 缓存 返回结果

代码语言:javascript复制
 @Override
  public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
    final Configuration configuration = ms.getConfiguration();
    final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
    final BoundSql boundSql = handler.getBoundSql();
    final String sql = boundSql.getSql();
    final Statement stmt; 
    
   //  当前sql , 并且是当前statement
    if (sql.equals(currentSql) && ms.equals(currentStatement)) {
      int last = statementList.size() - 1;
      stmt = statementList.get(last);
      applyTransactionTimeout(stmt);
      handler.parameterize(stmt);//fix Issues 322
      BatchResult batchResult = batchResultList.get(last);
      batchResult.addParameterObject(parameterObject);
    } else {
      Connection connection = getConnection(ms.getStatementLog());
      stmt = handler.prepare(connection, transaction.getTimeout());
      handler.parameterize(stmt);    //fix Issues 322
      currentSql = sql;
      currentStatement = ms;
      statementList.add(stmt);
      batchResultList.add(new BatchResult(ms, sql, parameterObject));
    }
    handler.batch(stmt);
    return BATCH_UPDATE_RETURN_VALUE;
  }

BatchExecutor VS ReuseExecutor

看输出 和 ReuseExecutor 感觉差不多,其实是有区别的

  • ReuseExecutor : 设置参数,执行,获取返回结果,然后在设置参数,执行,获取返回结果
  • BatchExecutor: 批量设置参数 , 执行 ,获取返回结果。

BatchExecutor仅执行一次,ReuseExecutor 执行多次

0 人点赞