MyBatis源码解析--加载流程(7)

本文深入探讨MyBatis中的Executor接口及其实现类,包括SimpleExecutor、ReuseExecutor、BatchExecutor和CachingExecutor,揭示它们在SQL执行、缓存管理和批量处理中的角色与机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SimpleExecutor
前面已经介绍了BaseExecutor,是Executor接口的直接继承,作用是提供模版,为它的继承类可以直接继承方法,其中SimpleExecutor会不需要关心一级缓存的问题,只要实现四个基本方法就可以。

public class SimpleExecutor extends BaseExecutor {

  public SimpleExecutor(Configuration configuration, Transaction transaction) {
    super(configuration, transaction);
  }

  @Override
  //执行更新操作
  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      //创建StatementHandler对象
      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
      //创建对应的Statement
      stmt = prepareStatement(handler, ms.getStatementLog());
      //执行更新
      return handler.update(stmt);
    } finally {
      closeStatement(stmt);
    }
  }

  @Override
  //查询的实现
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();//获取configuration对象
      //创建StatementHandler对象,
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      //StatementHandler对象创建stmt,并使用parameterHandler对占位符进行处理
      stmt = prepareStatement(handler, ms.getStatementLog());
      //通过statementHandler对象调用ResultSetHandler将结果集转化为指定对象返回
      return handler.<E>query(stmt, resultHandler);
    } finally {
    //关闭statement
      closeStatement(stmt);
    }
  }

  @Override
  protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
    Statement stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.<E>queryCursor(stmt);
  }

  @Override
  //不提供该方法
  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    return Collections.emptyList();
  }

  //创建Statement
  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    //获取connection对象的动态代理,添加日志能力;
    Connection connection = getConnection(statementLog);
    //通过不同的StatementHandler,利用connection创建(prepare)Statement
    stmt = handler.prepare(connection, transaction.getTimeout());
    //使用parameterHandler处理占位符
    handler.parameterize(stmt);
    return stmt;
  }

}

ReuseExecutor 可重用的Executor实现类,主要将statement缓存了,遇到相同的不需要反复创建statement

public class ReuseExecutor extends BaseExecutor {
//statement的缓存,key是SQL语句,value是Statement
  private final Map<String, Statement> statementMap = new HashMap<>();

  public ReuseExecutor(Configuration configuration, Transaction transaction) {
    super(configuration, transaction);
  }

  @Override
  //跟SimpleExecutor一样
  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);
  }

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Configuration configuration = ms.getConfiguration();//获取configuration对象
    //创建StatementHandler对象
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
  //StatementHandler对象创建stmt,并使用parameterHandler对占位符进行处理
    Statement stmt = prepareStatement(handler, ms.getStatementLog());
  //通过statementHandler对象调用ResultSetHandler将结果集转化为指定对象返回
    return handler.<E>query(stmt, resultHandler);
  }

  @Override
  protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
    Statement stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.<E>queryCursor(stmt);
  }

  @Override
  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
  //会将缓存所有的statement关闭并且将map清空
    for (Statement stmt : statementMap.values()) {
      closeStatement(stmt);
    }
    statementMap.clear();
    return Collections.emptyList();
  }
//跟SimpleExecutor的主要不同点
  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    BoundSql boundSql = handler.getBoundSql();
    String sql = boundSql.getSql();//获取sql语句
    if (hasStatementFor(sql)) {//根据sql语句检查是否缓存了对应的Statement
      stmt = getStatement(sql);//获取缓存的Statement
      applyTransactionTimeout(stmt);//设置新的超时时间
    } else {//缓存中没有statment,创建statment过程和SimpleExecutor类似
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      putStatement(sql, stmt);//放入缓存中
    }
  //使用parameterHandler处理占位符
    handler.parameterize(stmt);
    return stmt;
  }

  private boolean hasStatementFor(String sql) {
    try {
      return statementMap.keySet().contains(sql) && !statementMap.get(sql).getConnection().isClosed();
    } catch (SQLException e) {
      return false;
    }
  }

  private Statement getStatement(String s) {
    return statementMap.get(s);
  }

  private void putStatement(String sql, Statement stmt) {
    statementMap.put(sql, stmt);
  }

}

BatchExecutor 批量执行的Executor实现类

public class BatchExecutor extends BaseExecutor {

  public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;
//缓存多个Statement的对象,其中每个statement都缓存了多条SQL语句
  private final List<Statement> statementList = new ArrayList<>();
  //记录批处理的结果。每个BatchResult对应一个Statement元素
  private final List<BatchResult> batchResultList = new ArrayList<>();
  //记录当前的SQL语句
  private String currentSql;
  //记录当前的MappedStatement对象
  private MappedStatement currentStatement;

  public BatchExecutor(Configuration configuration, Transaction transaction) {
    super(configuration, transaction);
  }

  @Override
  //批处理只支持insert、update、delete等类型的SQL语句
  public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
  //获取配置内容
    final Configuration configuration = ms.getConfiguration();·
    //创建StatementHandler对象
    final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
    //得到sql语句
    final BoundSql boundSql = handler.getBoundSql();
    final String sql = boundSql.getSql();
    final Statement stmt;
    //如果当前执行的SQL模式跟上次执行的SQL模式相同并且对应的MappedStatement对象相同
    if (sql.equals(currentSql) && ms.equals(currentStatement)) {
    //获得集合中的最后一个Statement对象
      int last = statementList.size() - 1;
      stmt = statementList.get(last);
      //设置事务超时时间
      applyTransactionTimeout(stmt);
     handler.parameterize(stmt);//绑定实参
     //获得最后一次的BatchResult对象,并添加参数到其中
      BatchResult batchResult = batchResultList.get(last);
      batchResult.addParameterObject(parameterObject);
    } else {
    //如果不相同就会将其缓存到list中
      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.parameterize(stmt);
  //批处理
    handler.batch(stmt);
    return BATCH_UPDATE_RETURN_VALUE;
  }

  @Override
  //batchExecutor查询实现
  public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
      throws SQLException {
    Statement stmt = null;
    try {
      flushStatements();
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
      Connection connection = getConnection(ms.getStatementLog());
      stmt = handler.prepare(connection, transaction.getTimeout());
      handler.parameterize(stmt);
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

  @Override
  protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
    flushStatements();
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
    Connection connection = getConnection(ms.getStatementLog());
    Statement stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);
    return handler.<E>queryCursor(stmt);
  }

  @Override
  //批量处理SQL语句
  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    try {
    //用来储存批处理的结果
      List<BatchResult> results = new ArrayList<>();
      //如果要回滚就返回空集合
      if (isRollback) {
        return Collections.emptyList();
      }
      //遍历statementList集合
      for (int i = 0, n = statementList.size(); i < n; i++) {
      //获取对应的statement对象
        Statement stmt = statementList.get(i);
        applyTransactionTimeout(stmt);
        //获取对应的batchResult对象
        BatchResult batchResult = batchResultList.get(i);
        try {
        //更新batchResult中的SQL语句影响条数
          batchResult.setUpdateCounts(stmt.executeBatch());
          MappedStatement ms = batchResult.getMappedStatement();
          List<Object> parameterObjects = batchResult.getParameterObjects();
          //获取配置的KeyGenerator对象
          KeyGenerator keyGenerator = ms.getKeyGenerator();
          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);
            }
          }
          // 关闭statement对象
          closeStatement(stmt);
        } catch (BatchUpdateException e) {
          StringBuilder message = new StringBuilder();
          message.append(batchResult.getMappedStatement().getId())
              .append(" (batch index #")
              .append(i + 1)
              .append(")")
              .append(" failed.");
          if (i > 0) {
            message.append(" ")
                .append(i)
                .append(" prior sub executor(s) completed successfully, but will be rolled back.");
          }
          throw new BatchExecutorException(message.toString(), e, results, batchResult);
        }
        //添加到结果集
        results.add(batchResult);
      }
      return results;
    } finally {
    //关闭statement们
      for (Statement stmt : statementList) {
        closeStatement(stmt);
      }
      currentSql = null;
      statementList.clear();
      batchResultList.clear();
    }
  }

}

接下来是CachingExecutor,作用就是二级缓存,二级缓存是可以在多个sqlSession之间共享的,是以namespace为单位的。
其中在MappedStatement类中有private Cache cache,以为这可以给每个mapper指定不同的二级缓存。

public class CachingExecutor implements Executor {
//被委托的Executor对象
  private final Executor delegate;
  //TransactionalCacheManager 对象
  private final TransactionalCacheManager tcm = new TransactionalCacheManager();

  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    //设置delegate被当前执行器所包装
    delegate.setExecutorWrapper(this);
  }

  @Override
  //直接调用委托执行器中对应的方法
  public Transaction getTransaction() {
    return delegate.getTransaction();
  }

  @Override
  public void close(boolean forceRollback) {
    try {
      //如果强制回滚就回滚tcm
      if (forceRollback) { 
        tcm.rollback();
      } else {
      //如果强制提交,就提交
        tcm.commit();
      }
    } finally {
    //执行delegate对应的方法
      delegate.close(forceRollback);
    }
  }

  @Override
  public boolean isClosed() {
    return delegate.isClosed();
  }

  @Override
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
  //如果需要清空缓存就进行清空
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
	//获取sql语句信息,包括占位符,参数等信息
    BoundSql boundSql = ms.getBoundSql(parameterObject);
  //拼装缓存的key值
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  @Override
  public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
    flushCacheIfRequired(ms);
    return delegate.queryCursor(ms, parameter, rowBounds);
  }

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
	//从MappedStatement中获取二级缓存
    Cache cache = ms.getCache();
    if (cache != null) {
    //如果需要清空缓存就进行清空
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, boundSql);
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);//从二级缓存中获取数据
        if (list == null) {
          //二级缓存为空,才会调用BaseExecutor.query
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          //查询后放入二级缓存中
          tcm.putObject(cache, key, list); 
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  @Override
  public List<BatchResult> flushStatements() throws SQLException {
    return delegate.flushStatements();
  }

  @Override
  public void commit(boolean required) throws SQLException {
    delegate.commit(required);
    //执行tcm的commit方法
    tcm.commit();
  }

  @Override
  public void rollback(boolean required) throws SQLException {
    try {
      delegate.rollback(required);
    } finally {
      if (required) {
      //回滚tcm
        tcm.rollback();
      }
    }
  }

  private void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
    if (ms.getStatementType() == StatementType.CALLABLE) {
      for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
        if (parameterMapping.getMode() != ParameterMode.IN) {
          throw new ExecutorException("Caching stored procedures with OUT params is not supported.  Please configure useCache=false in " + ms.getId() + " statement.");
        }
      }
    }
  }

  @Override
  public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
  }

  @Override
  public boolean isCached(MappedStatement ms, CacheKey key) {
    return delegate.isCached(ms, key);
  }

  @Override
  public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
    delegate.deferLoad(ms, resultObject, property, key, targetType);
  }

  @Override
  public void clearLocalCache() {
    delegate.clearLocalCache();
  }
//如果需要清空缓存就进行清空
  private void flushCacheIfRequired(MappedStatement ms) {
    Cache cache = ms.getCache();
    if (cache != null && ms.isFlushCacheRequired()) {      
      tcm.clear(cache);
    }
  }

  @Override
  public void setExecutorWrapper(Executor executor) {
    throw new UnsupportedOperationException("This method should not be called");
  }

}

TransactionalCacheManager TransactionalCache 管理器

public class TransactionalCacheManager {
//因为一次事务操作可能会使用不同的mapper,所以需要用一个map来管理这些mapper对应的TransactionalCache
  private final Map<Cache, TransactionalCache> transactionalCaches = new HashMap<>();
//清空对应的缓存
  public void clear(Cache cache) {
    getTransactionalCache(cache).clear();
  }
//获得缓存中指定的值
  public Object getObject(Cache cache, CacheKey key) {
    return getTransactionalCache(cache).getObject(key);
  }
  //添加kv到缓存当中
  public void putObject(Cache cache, CacheKey key, Object value) {
    getTransactionalCache(cache).putObject(key, value);
  }
//提交所有的TransactionCache
  public void commit() {
    for (TransactionalCache txCache : transactionalCaches.values()) {
      txCache.commit();
    }
  }
//回滚所有的TransactionalCache
  public void rollback() {
    for (TransactionalCache txCache : transactionalCaches.values()) {
      txCache.rollback();
    }
  }

  private TransactionalCache getTransactionalCache(Cache cache) {
  //优先从transactionCaches获得Cache对象对应的TransactionalCache 对象,如果不存在就创建一个添加到缓存中。
    return transactionalCaches.computeIfAbsent(cache, TransactionalCache::new);
  }

}

TransactionalCache 支持事务的 Cache 实现类

public class TransactionalCache implements Cache {

  private static final Log log = LogFactory.getLog(TransactionalCache.class);
//二级缓存cache对象
  private final Cache delegate;
  //提交事务的时候会将底层的Cache清空
  private boolean clearOnCommit;
  //待提交的kv映射
  private final Map<Object, Object> entriesToAddOnCommit;
  //查找不到的key集合
  private final Set<Object> entriesMissedInCache;

  public TransactionalCache(Cache delegate) {
    this.delegate = delegate;
    this.clearOnCommit = false;
    this.entriesToAddOnCommit = new HashMap<>();
    this.entriesMissedInCache = new HashSet<>();
  }

  @Override
  public String getId() {
    return delegate.getId();
  }

  @Override
  public int getSize() {
    return delegate.getSize();
  }

  @Override
  public Object getObject(Object key) {
    // 从缓存中尝试获取value
    Object object = delegate.getObject(key);
    if (object == null) {
    //如果没有获取到就在entriesMissedInCache中添加相应的key
      entriesMissedInCache.add(key);
    }
    // 如果 clearOnCommit 为 true ,表示处于持续清空状态,则返回 null
    if (clearOnCommit) {
      return null;
    } else {
    //返回 value
      return object;
    }
  }

  @Override
  public ReadWriteLock getReadWriteLock() {
    return null;
  }

  @Override
  // 暂存 KV 到 entriesToAddOnCommit 中
  public void putObject(Object key, Object object) {
    entriesToAddOnCommit.put(key, object);
  }

  @Override
  public Object removeObject(Object key) {
    return null;
  }

  @Override
  public void clear() {
    clearOnCommit = true;
    //清空 entriesToAddOnCommit
    entriesToAddOnCommit.clear();
  }

  public void commit() {
  //如果 clearOnCommit 为 true ,则清空 delegate 缓存
    if (clearOnCommit) {
      delegate.clear();
    }
    // 将 entriesToAddOnCommit、entriesMissedInCache 刷入 delegate 中
    flushPendingEntries();
    // 重置
    reset();
  }

  public void rollback() {
  //从 delegate 移除出 entriesMissedInCache
    unlockMissedEntries();
    reset();
  }

  private void reset() {
    clearOnCommit = false;
    entriesToAddOnCommit.clear();
    entriesMissedInCache.clear();
  }

  private void flushPendingEntries() {
  // 将 entriesToAddOnCommit 刷入 delegate 中
    for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {
      delegate.putObject(entry.getKey(), entry.getValue());
    }
    // 将 entriesMissedInCache 刷入 delegate 中
    for (Object entry : entriesMissedInCache) {
      if (!entriesToAddOnCommit.containsKey(entry)) {
        delegate.putObject(entry, null);
      }
    }
  }

  private void unlockMissedEntries() {
    for (Object entry : entriesMissedInCache) {
      try {
        delegate.removeObject(entry);
      } catch (Exception e) {
        log.warn("Unexpected exception while notifiying a rollback to the cache adapter."
            + "Consider upgrading your cache adapter to the latest version.  Cause: " + e);
      }
    }
  }

}

分析完了Executor接口及其所有的实现类,那么看看Executor的调用:在Configuration中

//创建Executor对象
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
//获得执行器类型
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    //创建对应实现的Executor对象
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    //如果有<cache>节点,通过装饰器,添加二级缓存的能力
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    //通过interceptorChain遍历所有的插件为executor增强,添加插件的功能
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值