zoukankan      html  css  js  c++  java
  • Mybatis源码(五)

    6、SimpleExecutor.doQuery()

    1)创建StatementHandler

    在 configuration.newStatementHandler()中,new一个newStatementHandler,先得到RoutingStatementHandler。

    RoutingStatementHandler里面没有任何的实现,使用来创建基本的StatementHandler的。这里会根据MappedStatement里面的getStatementType
    决定StatementHandler的类型。默认是PREPARED(STATEMENT、PREPARED、CALLABLE)

      switch (ms.getStatementType()) {
          case STATEMENT:
            delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
            break;
          case PREPARED:
            // 创建 StatementHandler 的时候做了什么? >>
            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里面包含了处理参数的ParameterHandler和处理结果集的ResultSetHandler。

    这两个对象创建:

    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, 
    RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        ....
    
        this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
        this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, 
    parameterHandler, resultHandler, boundSql);
    }
    

    这三个对象都可以被插件拦截的,所以在创建之后都要用拦截器进行包装方法。

    // 植入插件逻辑(返回代理对象)
    parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
    
    resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
    
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    

    四大对象包装创建完成。

    QA:上面是三个对象,还有一个对象?是在什么时候创建的?(Executor)

    1. 创建Statement

    用new出来的statementHandler创建statement对象。

    如果有插件包装,会先走到被拦截的业务逻辑,SimpleExecutor对象

    // 获取一个 Statement对象
    stmt = prepareStatement(handler, ms.getStatementLog());
    

    prepareStatement方法对语句执行,处理参数:

    // 执行查询
    handler.query(stmt, resultHandler);
    

    这里会调用parameterHandler设置参数,如果有插件包装,会先走到被拦截的业务逻辑。

    @Override
    public void parameterize(Statement statement) throws SQLException {
        parameterHandler.setParameters((PreparedStatement) statement);
    }
    

    执行StatementHandler的query方法。

    RoutingStatementHandler的query()方法。

    delegate委派,最终执行PreparedStatementHandler的query()方法。

    4)执行PreparedStatement的execute方法

    // 到了JDBC的流程
    ps.execute();
    

    后面就是JDBC的PreparedStatement的执行了。

    5)resultSetHandler处理结果集

    如果有插件包装,会先走到被拦截的业务逻辑。

    // 处理结果集
    return resultSetHandler.handleResultSets(ps);
    
    QA:怎么把ResultSet转换成List<Object>的呢?
    
        resultSetHandler只有一个实现类:DefaultResultSetHandler。也就是执行了DefaultResultSetHandler的handleResultSets()方法。
    首先我们会先拿到第一个结果集,如果没有配置一个查询返回多个结果集的情况,一般只有一个结果集。如果下面的这个while循环我们不使用,
    就是执行一次。
    然后调用handleResultSet()方法。
    
    @Override
    public List<Object> handleResultSets(Statement stmt) throws SQLException {
        ...
    
        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++;
        }
        ...
            if (parentMapping != null) {
                ...
                    handleResultSet(rsw, resultMap, null, parentMapping);
            }
    }
    

    调用代理方法,执行SQL

    image

  • 相关阅读:
    NYOJ 625 笨蛋的难题(二)
    NYOJ 102 次方求模
    ZJU Least Common Multiple
    ZJUOJ 1073 Round and Round We Go
    NYOJ 709 异形卵
    HDU 1279 验证角谷猜想
    BNUOJ 1015 信息战(一)——加密程序
    HDU 1202 The calculation of GPA
    "蓝桥杯“基础练习:字母图形
    "蓝桥杯“基础练习:数列特征
  • 原文地址:https://www.cnblogs.com/snail-gao/p/13254836.html
Copyright © 2011-2022 走看看