`

MyBatis原理(2)-执行流程 3 处理结果集

 
阅读更多
DefaultResultSetHandler#handleResultSets 处理结果集

@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是对ResultSet元数据的封装
    ResultSetWrapper rsw = getFirstResultSet(stmt);
   //获取返回类型-resultType会被转换为Inline的ResultMap(id变为namespace+“Inline” see MapperBuilderAssistant#getStatementResultMaps)
    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
  //如果结果集不为空,resultMapCount<1抛出异常
    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);
  }
//处理当前结果集
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
    try {
      if (parentMapping != null) {
        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
      } else {
        if (resultHandler == null) {
           //结果处理器为空resultHandler从构造Executor传入
          //构造默认的结果处理器,使用objectFactory创建结果集
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
          //处理当前ResultMap中每一行 
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          multipleResults.add(defaultResultHandler.getResultList());
        } else {
          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
        }
      }
    } finally {
      //
      // issue #228 (close resultsets)
      closeResultSet(rsw.getResultSet());
    }
  }


  public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
   //如果有嵌套的(子句中包含select属性)
    if (resultMap.hasNestedResultMaps()) {
     //确保字句中没有分页
      ensureNoRowBounds();
    //确保子句中没有ResultHandler
      checkResultHandler();
    //处理嵌套的ResultMap
      handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    } else {
      handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    }
  }


 private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    //初始化结果上下文--用于存储当前返回对象和结果条数,实际上就是一个计数器
    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    //跳过指定偏移量---分页
    skipRows(rsw.getResultSet(), rowBounds);
    //context中结果条数小于rowBounds的limit获取结果集下一个
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
     //首先循环处理嵌套鉴别器,将解析后的最后一个resultMap作为当前resultMap,无鉴别器则返回当前resultMap
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
       //获取当前行的值
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      //如过parentMapping不为空,将rowvalue设置给parent,否则回调自己的ResultHandler
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }


 private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
     //ResultLoaderMap存储了LoadPair的hashMap,对应一个对象,每一个LoadPair则对应
   //对象的每一个属性和其延迟加载器 ResultLoader,ResultLoader封装了executor,parameterObject,objectFactory,cacheKey等必要的一切属性用来再次执行sql(包括当前线程和其他线程)
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
  //初始化返回对象,如过有嵌套查询则创建lazyLoader的代理对象,并返回
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
    // 给rowvalue设置值
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(rowValue);
      boolean foundValues = this.useConstructorMappings;
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
    }
    return rowValue;
  }

分享到:
评论

相关推荐

    Mybatis逆向生成工具mybatis-generator-core-1.3.2.jar包

    这里我们将深入探讨MBG的核心功能、工作原理以及如何使用mybatis-generator-core-1.3.2.jar这个版本来自动化生成代码。 首先,MyBatis Generator基于数据库表结构,通过配置文件指定数据库连接信息、表名以及需要...

    逆向工程mybatis-generator-1.3.2

    在这个场景中,“逆向工程mybatis-generator-1.3.2”指的是对MyBatis Generator 1.3.2版本的源代码或执行流程进行逆向分析。MyBatis Generator(MBG)是一个强大的工具,能够自动生成MyBatis接口和映射器XML文件,...

    mybatis-3-master.zip

    总的来说,`mybatis-3-master` 源码分析可以帮助我们理解 MyBatis 内部的工作原理,提高我们对 SQL 执行流程、对象映射机制的理解,从而更好地优化数据库操作,提升系统性能。同时,通过阅读源码,开发者还能学习到...

    mybatis-3-mybatis-3.3.0-SNAPSHOT.zip

    8. StatementHandler:处理PreparedStatement对象,设置SQL参数和获取结果集。 9. MapperRegistry:注册Mapper接口和对应的MappedStatement,使得我们可以通过Mapper接口调用SQL。 在MyBatis源码中,你可以看到...

    mybatis-3-mybatis-3.5.4-src-read.zip

    在本压缩包“mybatis-3-mybatis-3.5.4-src-read.zip”中,包含了作者对MyBatis 3.5.4版本源码的阅读理解,特别进行了关键部分的注解和流程解析,对于学习和深入理解MyBatis的工作原理非常有帮助。 1. **MyBatis架构...

    mybatis代码自动生成工具mybatis-generator-core-1.3.2

    总的来说,Mybatis Generator是Mybatis框架下的一个重要辅助工具,它极大地简化了开发流程,提高了开发效率,尤其是在处理大量表和字段的项目中,其价值尤为显著。对于任何使用Mybatis的团队来说,掌握并合理利用...

    mybatis-3-mybatis-3.4.1源码

    3. **StatementHandler**:处理SQL语句,包括预编译、设置参数、获取结果集等。它通过PreparedStatement和ResultSet与数据库进行交互。 4. **ParameterHandler**:处理输入参数,将Java对象转换为数据库可识别的...

    Mybatis---从最基础案例带你深入了解“她”

    4. **结果集处理**: 自动将查询结果映射成Java对象,这样就不需要手动遍历结果集并将每一列的值转换成Java对象了。 #### 五、环境搭建与配置 1. **下载MyBatis**: - 从GitHub ...

    mybatis-auto-generator-core逆向自动生成

    2. **工作原理** - 数据库连接:MyBatis-Auto-Generator-Core首先需要建立到数据库的连接,通过JDBC获取数据库元数据,包括表名、列名、数据类型等信息。 - 模板引擎:然后,它使用模板引擎(如FreeMarker或...

    mybatis-src-3.2.2.zip

    MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 在...

    mybatis-3-mybatis-3.3.0.tar.gz

    2. **结果映射**:MyBatis 提供了自动化的结果映射功能,可以根据数据库查询结果自动将数据行映射到 Java 对象上,同时也支持自定义映射,以处理复杂的数据库结果集。 3. **缓存机制**:为了提高性能,MyBatis 实现...

    mybatis-3-mybatis-3.1.0.zip

    MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 在...

    mybatis-generator-core-1.3.2

    MyBatis Generator 的工作原理是通过读取数据库元数据,根据预设的模板生成对应的 Java 源代码。它支持多种数据库,包括 MySQL、Oracle、SQL Server 等。在使用 MBG 时,我们需要创建一个 XML 配置文件,其中定义了...

    mybatis-3-mybatis-3.2.6.tar.gz

    5. 结果处理:`ResultSetHandler`接口用于处理SQL查询返回的结果集,它可以将数据映射到Java对象或集合。MyBatis支持多种映射策略,包括一对一、一对多、多对多等关系的映射。 6. 缓存:MyBatis内置了两级缓存,一...

    lijie_study-mybatis-3-master.zip

    通过深入研究"Mybatis-3"的源码,我们可以理解其内部的执行流程,例如Executor的执行策略、StatementHandler的预编译和执行过程、ParameterHandler参数绑定的逻辑,以及ResultSetHandler结果集处理的细节。...

    mybatis视频教学-

    12. **MyBatis 执行流程**:了解 MyBatis 如何解析 XML 或注解,生成 PreparedStatement,执行 SQL,处理结果集,以及事务提交或回滚的过程。 13. **实战项目**:通过一个完整的案例,实践 MyBatis 的集成,包括...

    跑通的Mybatis后端源码-WhenToMint

    Mybatis是一个轻量级的ORM(Object-Relational Mapping)框架,它避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis通过XML或注解方式配置和映射原生信息,将接口和Java的POJOs(Plain Old Java ...

    mybatis-3-mybatis-3.2.3.tar.gz

    MyBatis 是一款著名的Java持久层框架,它简化了数据库操作与Java对象之间的映射,提供了灵活的SQL构建和执行机制。在MyBatis-3.2.3这个版本中,我们可以深入研究其源码,了解其内部工作原理,这对于Java开发者尤其是...

    Mybatis--SQL解析流程图

    通过上述分析,我们可以清晰地了解到Mybatis中SQL解析的整体流程:从创建SqlSessionFactory开始,到打开SqlSession,再到获取Mapper代理对象,最后执行SQL语句并获取结果。这一过程不仅展示了Mybatis强大的SQL解析...

    MyBatis-讲义-2.2.docx

    5. **处理结果集**:遍历ResultSet并处理数据。 6. **释放资源**:确保所有使用的资源被正确关闭,避免内存泄漏等问题。 #### 七、MyBatis优势 1. **简化数据库操作**:通过配置文件或注解,简化了SQL语句的编写、...

Global site tag (gtag.js) - Google Analytics