mybatis 查询运行原理(源码解析)

从sqlsessionfactory.openSession处得到session之后,这个session是defaultSqlSession

private static SqlSessionFactory sqlSessionFactory = null;

       /**

        * 初始化Session工厂

        *

        * @throws IOException

        */

       private static void initialFactory() throws IOException {

             String resource = "mybatis-config.xml";

             InputStream inputStream = Resources.getResourceAsStream(resource);

             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

       }

       /**

        * 获取Session

        *

        * @return

        */

       public static SqlSession getSession() {

             if (sqlSessionFactory == null) {

                    try {

                           initialFactory();

                    } catch (IOException e) {

                           e.printStackTrace();

                    }

             }

             return sqlSessionFactory.openSession(true);

       }

调用selectList方法,在selectList中调用executor.query方法 

@Override

  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {

    try {

      MappedStatement ms = configuration.getMappedStatement(statement);

      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

    } catch (Exception e) {

      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);

    } finally {

      ErrorContext.instance().reset();

    }

  }

这个executor 是CachingExecutor(在初始化sqlsession中Configuration 已经初始化过了)

Configuration.class

protected boolean cacheEnabled = true;

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {

    executorType = executorType == null ? defaultExecutorType : executorType;

    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;

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

    }

    if (cacheEnabled) {

      executor = new CachingExecutor(executor);

    }

    executor = (Executor) interceptorChain.pluginAll(executor);

    return executor;

  }

CachingExecutor 类中获取BoundSql,生成缓存key,在第二个query方法中判断是否缓存命中,否则执行delegate.<E> query

@Override

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {

    BoundSql boundSql = ms.getBoundSql(parameterObject);

    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);

    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

  }

 @Override

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)

      throws SQLException {

    Cache cache = ms.getCache();

    if (cache != null) {

      flushCacheIfRequired(ms);

      if (ms.isUseCache() && resultHandler == null) {

        ensureNoOutParams(ms, parameterObject, boundSql);

        @SuppressWarnings("unchecked")

        List<E> list = (List<E>) tcm.getObject(cache, key);

        if (list == null) {

          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

          tcm.putObject(cache, key, list); // issue #578 and #116

        }

        return list;

      }

    }

    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

  }

执行BaseExecutor.query方法,再调用queryFromDatabase方法 

@Override

  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) {

        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);

      } else {

        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

      }

    } finally {

      queryStack--;

    }

    if (queryStack == 0) {

      for (DeferredLoad deferredLoad : deferredLoads) {

        deferredLoad.load();

      }

      // issue #601

      deferredLoads.clear();

      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {

        // issue #482

        clearLocalCache();

      }

    }

    return list;

  }

queryFromDatabase方法中调用doQuery方法执行查询

 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;

  }

doQuery是抽象方法,由子类完成重写,这里调用的是SimpleExecutor类,也是在sqlsession初始化中初始化的 

@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();

      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);

      stmt = prepareStatement(handler, ms.getStatementLog());

      return handler.<E>query(stmt, resultHandler);

    } finally {

      closeStatement(stmt);

    }

  }

这里用到了一个设计模式:装饰器模式(同一个实现接口或者同一个继承类,在子类A中调用子类B中的方法),也是单一原则的体现(每一个类专注于一件事情)

调用prepareStatement方法,parameterize方法中使用parameterHandler 完成set参数动作 

 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {

    Statement stmt;

    Connection connection = getConnection(statementLog);

    stmt = handler.prepare(connection, transaction.getTimeout());

    handler.parameterize(stmt);

    return stmt;

  }

 @Override

  public void parameterize(Statement statement) throws SQLException {

    parameterHandler.setParameters((PreparedStatement) statement);

  }

调用query方法,使用java.sql.prepareStatement 查询数据,最后使用resultSetHandler 封装结果集,返回List<Object>

@Override

  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {

    PreparedStatement ps = (PreparedStatement) statement;

    ps.execute();

    return resultSetHandler.<E> handleResultSets(ps);

  }

//封装结果集

 @Override

  public List<Object> handleResultSets(Statement stmt) throws SQLException {

    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<Object>();

    int resultSetCount = 0;

    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();

    int resultMapCount = resultMaps.size();

    validateResultMapsCount(rsw, resultMapCount);

    while (rsw != null && resultMapCount > resultSetCount) {

      ResultMap resultMap = resultMaps.get(resultSetCount);

      handleResultSet(rsw, resultMap, multipleResults, null);

      rsw = getNextResultSet(stmt);

      cleanUpAfterHandlingResultSet();

      resultSetCount++;

    }

    String[] resultSets = mappedStatement.getResultSets();

    if (resultSets != null) {

      while (rsw != null && resultSetCount < resultSets.length) {

        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);

        if (parentMapping != null) {

          String nestedResultMapId = parentMapping.getNestedResultMapId();

          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);

          handleResultSet(rsw, resultMap, null, parentMapping);

        }

        rsw = getNextResultSet(stmt);

        cleanUpAfterHandlingResultSet();

        resultSetCount++;

      }

    }

    return collapseSingleResultList(multipleResults);

  }

猜你喜欢

转载自blog.csdn.net/orpis/article/details/81145064