Mybatis源码解析 Executor

作者: 三斤牛肉 | 来源:发表于2017-05-31 18:46 被阅读46次

Executor是mybaits的核心接口之一,他用于执行数据库具体操作,包括但不限于CRUD,commit,rollback等。

image.png

Exector有2个子类BaseExecutor和CachingExecutor。

CachingExecutor

只是一个包装(wrapper)类,再原Exector入参的基础上增加了缓存功能。

BaseExecutor

抽象类,它实现了所有公共部分,将核心的具体操作委派给子类:

image.png

Executor一共有3个子类:

image.png

SimpleExecutor

mybatis默认实现,也是最基础的实现。

ReuseExecutor

增加了一个Statement的缓存Map,key是sql

private final Map<String, Statement> statementMap = new HashMap<String, Statement>();

因为一个SqlSession包含一个Executor:

final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);

所以该map只有在当前session中有效,在Statement关闭时清楚缓存。

BatchExecutor

用于批量更新操作

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和MappedStatement与当前一致时,缓存当前的parameterObject
//这里为什么是取最后一个statement而不是用map去保存,是为了保证操作的一致性。
    if (sql.equals(currentSql) && ms.equals(currentStatement)) {
      int last = statementList.size() - 1;
      stmt = statementList.get(last);
      BatchResult batchResult = batchResultList.get(last);
      batchResult.addParameterObject(parameterObject);
    } else {
      Connection connection = getConnection(ms.getStatementLog());
      stmt = handler.prepare(connection);
      currentSql = sql;
      currentStatement = ms;
      statementList.add(stmt);//Statement和MappedStatement一致,为statementList最后一个
      batchResultList.add(new BatchResult(ms, sql, parameterObject));
    }
    handler.parameterize(stmt);
//批量执行
    handler.batch(stmt);
    return BATCH_UPDATE_RETURN_VALUE;
  }
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    try {
      List<BatchResult> results = new ArrayList<BatchResult>();
      if (isRollback) {
        return Collections.emptyList();
      } else {
        for (int i = 0, n = statementList.size(); i < n; i++) {
          Statement stmt = statementList.get(i);
          BatchResult batchResult = batchResultList.get(i);
          try {
            batchResult.setUpdateCounts(stmt.executeBatch());//批量执行SQL
            MappedStatement ms = batchResult.getMappedStatement();
            List<Object> parameterObjects = batchResult.getParameterObjects();
            KeyGenerator keyGenerator = ms.getKeyGenerator();
//jdbc3.0主键生成方式
            if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
              Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
              jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
            } else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141
              for (Object parameter : parameterObjects) {
                keyGenerator.processAfter(this, ms, stmt, parameter);
              }
            }
          } catch (BatchUpdateException e) {
            ...
          }
          results.add(batchResult);
        }
        return results;
      }
    } finally {
      for (Statement stmt : statementList) {//关闭所有链接
        closeStatement(stmt);
      }
      ...
    }

相关文章

网友评论

    本文标题:Mybatis源码解析 Executor

    本文链接:https://www.haomeiwen.com/subject/acjjfxtx.html