mybatis运行过程深度解析(三)

我们知道:通过XMLConfigBuild我们获取了把xml配置文件解析成的configuration对象,然后我们使用它来创建了SQLSessionFactory,这个过程封装成了一个SQLSessionFactoryBuild类;有了SQLSessionFactory我们讲究直接可以获取到SQLSession对象了;然后我们又分析了SQLSession的运行过程,它是通过映射器的注册器动态代理生成的Mapper对象,然后看了他的动态代理生成的过程,走到了这里:

  private <K, V> Map<K, V> executeForMap(SqlSession sqlSession, Object[] args) {
    Map<K, V> result;
    Object param = method.convertArgsToSqlCommandParam(args);
    if (method.hasRowBounds()) {
      RowBounds rowBounds = method.extractRowBounds(args);
      result = sqlSession.<K, V>selectMap(command.getName(), param, method.getMapKey(), rowBounds);
    } else {
      result = sqlSession.<K, V>selectMap(command.getName(), param, method.getMapKey());
    }
    return result;
  }

那现在我们继续往下看,到底SQLSession怎么给我们执行sql语句的:

它调用了sqlSession的Map<K, V> selectMap的方法,咱们看它的实现,它的实现在DefaultSqlSession类中,

 @Override
  public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
    return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
  }

  @Override
  public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
    final List<? extends V> list = selectList(statement, parameter, rowBounds);
    final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<K, V>(mapKey,
        configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
    final DefaultResultContext<V> context = new DefaultResultContext<V>();
    for (V o : list) {
      context.nextResultObject(o);
      mapResultHandler.handleResult(context);
    }
    return mapResultHandler.getMappedResults();
  }

继续看:

final List<? extends V> list = selectList(statement, parameter, rowBounds);
通过这个方法,我们找到了executor,源码如下:
  @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是什么?它是执行器,是SQLSession下的四大对象之一;由它来调度另外三个对象statementHandler、ParameterHandler、ResultSetHandler等来执行sql。

那我们继续说一下其它三个对象的作用:

1)statementHandler:使数据库的Statement执行操作,它是核心,起承上启下的作用;

2)ParameterHandler:用来处理sql的参数;

3)ResultSetHandler:是执行数据的返回处理的;

那我们继续看它是怎么调度的:

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

我们一层层进入,终于找到了org.apache.ibatis.executor.SimpleExecutor下的doQuery方法和它下面要调用的prepareStatement方法:

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

显然我们能够看到mybatis根据configuration来构建的StatementHandler,然后调用prepareStatement方法,对sql进行编译和参数的初始化;它的过程是:

1)首先调用了StatementHandler的prepare方法执行了预编译和基础的设置:

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

2)然后通过StatementHandler的parameterize方法设置参数

handler.parameterize(stmt);

进去之后

  @Override
  public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }
我们看到了parameterHandler进行的处理;

然后将处理好的对象再次交给StatementHandler的<E>query方法进行执行:

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    String sql = boundSql.getSql();
    statement.execute(sql);
    return resultSetHandler.<E>handleResultSets(statement);
  }

我们接下来继续跟进:

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    return delegate.<E>query(statement, resultHandler);
  }
在这里我们进入了RoutingStatementHandler,它实现了StatementHandler接口,

public class RoutingStatementHandler implements StatementHandler {

  private final StatementHandler delegate;

  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

    switch (ms.getStatementType()) {
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    }

我们能够看到它创建StatementHandler对象,然后我们找到了resultSetHandler

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return resultSetHandler.<E> handleResultSets(ps);
  }
到这里整个SQLSession如何去处理并执行sql的流程就明白了;

大体描述一下流程,如上图。



猜你喜欢

转载自blog.csdn.net/hbl6016/article/details/80160723