Mybatis源码解析(二) Executor

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

Mybatis源码解析(二) Executor_第1张图片
image.png

Exector有2个子类BaseExecutor和CachingExecutor。

CachingExecutor

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

BaseExecutor

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

image.png

Executor一共有3个子类:

Mybatis源码解析(二) Executor_第2张图片
image.png

SimpleExecutor

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

ReuseExecutor

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

private final Map statementMap = new HashMap();

因为一个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 doFlushStatements(boolean isRollback) throws SQLException {
    try {
      List results = new ArrayList();
      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 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);
      }
      ...
    }
 
 

SqlSession周期的一级缓存

private  List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
  //缓存
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }

你可能感兴趣的:(Mybatis源码解析(二) Executor)