不明白mybatis源码中queryStack变量的作用是什么?

在阅读mybatis源码时,发现问题:

源码org.apache.ibatis.executor.BaseExecutor#query,如下:

protected int queryStack;
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler,
      CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        //处理Callable类型,还需要绑定IN/OUT参数
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        //本地缓存没有结果,直接查询数据库
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      // ... codeA ...
    }
    return list;
}

我无法明白这个queryStack变量的意义。
通过控制流程来看:

  1. 假如这段代码允许多线程并发,那么int变量一定会出现线程安全问题。
  2. 假如这段代码仅允许单线程跑,那么只可能是因为存在递归的情况,才需要引用int来记录stack,但是我跟代码半天,也没有发现哪里会递归。

有没有大佬讲讲啥时候这个方法会递归调用?或者是其他作用。

阅读 932
1 个回答

首先 BaseExecutor 就没有设计为允许多线程并发调用,因为你看它的代码就知道一个 BaseExecutor 对象包含一个 Transaction,这样的设计表示它专属于某个数据库事务,而数据库事务的执行就是单线程的。换句话说,用户在调用 SqlSessionFactory.openSession() 方法,得到 SqlSession 对象之后,都不可以使其被多个线程访问。

其次说到 queryStack 这个变量。确实框架本身并没有直接的递归调用,但框架设计了一个扩展机制,你可以在 InterceptorChain 里面看到,框架允许用户创建自己的 Interceptor 实现类。这个实现类将会在 Configuration.newStatementHandler() 方法中被调用,而这个方法会在 BaseExecutor 的多个子类中用到。举一个例子,调用链如下:

BaseExecutor#query()
  -> BaseExecutor#queryFromDatabase()
    -> BaseExecutor#doQuery()
      -> SimpleExecutor#doQuery()  // 这里以 SimpleExecutor 为例
        -> Configuration#newStatementHandler()

调用到了这里,用户创建的 Interceptor 就开始起作用了,框架无法预料用户会怎么写,如果用户在这个过程中又调用了 Executor.query() 方法,这就可能会制造出一个递归。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题