mybatis——Executor

映射器了解完了,sqlSession.select()实际上是Executor.query(),所以sql执行实际是executor执行的。

一、BaseExecutor

BaseExecutor是一个Executor的顶级抽象类,实现了Executor接口,定义sql执行的执行器。

模板设计模式的运用,将一部分方法逻辑延迟给子类来实现。(专业术语:钩子)

BaseExecutor有4个实现子类:

下面介绍下BaseExecutor的实现

1、变量与构造方法

/* org.apache.ibatis.executor.BaseExecutor */
  protected Transaction transaction;//事务
  protected Executor wrapper;//一个指向自己(this)的指针

  protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
  
  //mybatis的一级缓存
  protected PerpetualCache localCache;
  protected PerpetualCache localOutputParameterCache;
  //configuration对象
  protected Configuration configuration;

  protected int queryStack;
  //关闭状态哨兵
  private boolean closed;

  protected BaseExecutor(Configuration configuration, Transaction transaction) {
    this.transaction = transaction;
    this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
    this.localCache = new PerpetualCache("LocalCache");
    this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
    this.closed = false;
    this.configuration = configuration;
    this.wrapper = this;
  }

2、主要方法

由于没有注释,所以方法作用不是很清楚,简单分了下类

/* org.apache.ibatis.executor.Executor */
  ResultHandler NO_RESULT_HANDLER = null;

  /* 
   * sql执行方法CRUD
   */
  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;

  /*
   * 跟BatchExecutor有关的方法,暂时还不知道有什么用
   */
  List<BatchResult> flushStatements() throws SQLException;

  /*  
   * 事务相关
   */ 
  void commit(boolean required) throws SQLException;

  void rollback(boolean required) throws SQLException;
  
  Transaction getTransaction();

  /*  
   * 缓存相关
   */
  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);

  /*  
   * 自身状态相关
   */
  void close(boolean forceRollback);

  boolean isClosed();

  void setExecutorWrapper(Executor executor);

① sql方法执行相关

/* 方法过多,选取一个方法研究 */
/* org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler) */
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //获取sql
    BoundSql boundSql = ms.getBoundSql(parameter);
    //创建缓存key
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
 }

  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    //sql校验是否存在
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    //关闭哨兵,如果executor已关闭,抛出异常
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    //清除缓存(mybatis一级缓存)
    //queryStack == 0 :正在执行的select类型的sql的个数
    //并且 mappedStatement的flushCacheRequired属性为true,对应前面<sql>中的flushCache属性默认:<select> : false ; 非<select> true
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      //根据cacheKey获取缓存
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        //缓存存在,由于默认preparedStatement,这里相当于空方法
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        //数据库查询
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      //延迟加载,什么时候需要延迟加载
      //关联映射时,select返回的resultMap中嵌套了子select查询,延迟加载将select与嵌套的子select查询的结果resultMap关联起来。
      //具体例子 订单查询的结果中嵌套订单详情查询。
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        // 一级缓存的作用域是statement级别,清除缓存;默认的是session会话级别,不清楚缓存
        clearLocalCache();
      }
    }
    return list;
  }
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql):数据库查询
  private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> 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;
  }

  protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
      throws SQLException;

查看了下BaseExecutor类,钩子方法只有4个,都是与sql执行相关的方法。

  protected abstract int doUpdate(MappedStatement ms, Object parameter)
      throws SQLException;
  protected abstract List<BatchResult> doFlushStatements(boolean isRollback)
      throws SQLException;
  protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
      throws SQLException;
  protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)
      throws SQLException;

这里看看各个子类是怎样执行的,还是以doQuery()方法为研究点

SimpleExecutor(默认的Executor):每创建一个statement,执行完sql后,关闭statement

  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      //获取configuration对象
      Configuration configuration = ms.getConfiguration();
      //应用configuration的设置--<settings>标签,驼峰命名等
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      //sql执行 statement.execute()
      //查询结果处理resultHandler.handleResultSet();result-->resultMap(处理嵌套sql)
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    //获取连接
    Connection connection = getConnection(statementLog);
    //创建statement,并设置sql,默认是PreparedStatement
    stmt = handler.prepare(connection, transaction.getTimeout());
    //设置参数parameters
    handler.parameterize(stmt);
    return stmt;
  }

ReuseExecutor:创建一个statement,放入到一个statementMap<sql,statement>中实现statement复用,当然statement不是一直有效,会设置一个超时时间

扫描二维码关注公众号,回复: 9697301 查看本文章
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
    Statement stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.<E>query(stmt, resultHandler);
  }

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    BoundSql boundSql = handler.getBoundSql();
    String sql = boundSql.getSql();
    if (hasStatementFor(sql)) {
      //statement复用
      stmt = getStatement(sql);
      //statement有效时间
      applyTransactionTimeout(stmt);
    } else {
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      putStatement(sql, stmt);
    }
    handler.parameterize(stmt);
    return stmt;
  }

BatchExecutor:创建一个statement,执行完sql,关闭statement,与SimpleExecutor不同:

  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);
    }
  }

ResultLoaderMap.ClosedExecutor:

    protected <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
      throw new UnsupportedOperationException("Not supported.");
    }

1

猜你喜欢

转载自www.cnblogs.com/wqff-biubiu/p/12449786.html