Mybatis中的ExecutorType

在mybatis的ExecutorType中,执行sql有三种执行模式,分别为
SIMPLE
REUSE
BATCH
这三种模式分别对应着三种执行器
SimpleExecutor、ReuseExecutor、BatchExecutor
1.SimpleExecutor

@Override
  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
      stmt = prepareStatement(handler, ms.getStatementLog());//创建statement
      return handler.update(stmt);
    } finally {
      closeStatement(stmt);//关闭statement,意味着下一次使用需要重新开启statement
    }
  }

SimpleExecutor是每次都会关闭statement,意味着下一次使用需要重新开启statement。
2.ReuseExecutor

@Override
 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
   Configuration configuration = ms.getConfiguration();
   StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
   Statement stmt = prepareStatement(handler, ms.getStatementLog());
   return handler.update(stmt);//没有关闭statement
 }

ReuseExecutor不会关闭statement,而是把statement放到缓存中。缓存的key为sql语句,value即为对应的statement。也就是说不会每一次调用都去创建一个 Statement 对象,而是会重复利用以前创建好的(如果SQL相同的话),这也就是在很多数据连接池库中常见的 PSCache 概念 。
3.BatchExecutor

 @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;
    if (sql.equals(currentSql) && ms.equals(currentStatement)) {//判断当前使用sql和statement是否是上一次的statement和sql
      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);//否则创建statement并存入
      batchResultList.add(new BatchResult(ms, sql, parameterObject));
    }
  // handler.parameterize(stmt);
    handler.batch(stmt);//仅仅是存入批处理参数而不执行
    return BATCH_UPDATE_RETURN_VALUE;//始终返回一个常量
  }

总结
SimpleExecutor是一种常规执行器,每次执行都会创建一个statement,用完后关闭。
ReuseExecutor是可重用执行器,将statement存入map中,操作map中的statement而不会重复创建statement。
BatchExecutor是批处理型执行器,doUpdate预处理存储过程或批处理操作,doQuery提交并执行过程。

性能对比

SimpleExecutor 比 ReuseExecutor 的性能要差 , 因为 SimpleExecutor 没有做 PSCache。为什么做了 PSCache 性能就会高呢 , 因为当SQL越复杂占位符越多的时候预编译的时间也就越长,创建一个PreparedStatement对象的时间也就越长。猜想中BatchExecutor比ReuseExecutor功能强大性能高,实际上并非如此,BatchExecutor是没有做PSCache的。BatchExecutor 与 SimpleExecutor 和 ReuseExecutor 还有一个区别就是 , BatchExecutor 的事务是没法自动提交的。因为 BatchExecutor 只有在调用了 SqlSession 的 commit 方法的时候,它才会去执行 executeBatch 方法。

如何在项目中设置这些模式
mybatis+spring中ExecutorType的使用

<!--配置一个可以进行批量执行的sqlSession  -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>
    <constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
```
posted @ 2021-11-22 21:35  一刹流云散  阅读(2602)  评论(0编辑  收藏  举报