Mybatis之Executor执行器

2021-03-30  本文已影响0人  engineer_tang

Executor执行器接口定义如下:

public interface Executor {

  ResultHandler NO_RESULT_HANDLER = null;

  int update(MappedStatement ms, Object parameter) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

  <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;

  List<BatchResult> flushStatements() throws SQLException;

  void commit(boolean required) throws SQLException;

  void rollback(boolean required) throws SQLException;

  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

  boolean isCached(MappedStatement ms, CacheKey key);

  void clearLocalCache();

  void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);

  Transaction getTransaction();

  void close(boolean forceRollback);

  boolean isClosed();

  void setExecutorWrapper(Executor executor);

}

执行器子类实现结构图如下:


image.png

1. CachingExecutor类

这里用到了装饰器模式,抽象构件角色是BaseExecutor,具体构件角色是SimpleExecutor、ReuseExecutor、BatchExecutor,这里没有抽象装饰角色,具体装饰角色是CachingExecutor,通过该模式完成了缓存功能的实现。

2. SimpleExecutor和ReuseExecutor对比

SimpleExecutor是默认的执行器,每次执行都会创建一个Statement对象,使用完成会调用closeStatement方法比比使用完的Statement。如下所示:


image.png

而Reuse使用完成不会关闭Statement,而是会存入自己维护的HashMap结构的statementMap容器中,方便下次复用。


image.png
请看ReuseExecutor类的如下代码:
  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    BoundSql boundSql = handler.getBoundSql();
    String sql = boundSql.getSql();
    if (hasStatementFor(sql)) {
      stmt = getStatement(sql);
      applyTransactionTimeout(stmt);
    } else {
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      putStatement(sql, stmt);
    }
    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);
  }

从如上代码可以知道,每次获取Statement对象时,会先调用hasStatementFor方法看statementMap容器中是否有可直接使用的Statement对象,如果没有就新创建一个,并且缓存到statementMap容器中。

3. BatchExecutor

上一篇下一篇

猜你喜欢

热点阅读