首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mybatis的结果集处理 顶

Mybatis的结果集处理 顶

作者头像
算法之名
发布2019-08-20 10:27:35
3.8K0
发布2019-08-20 10:27:35
举报
文章被收录于专栏:算法之名算法之名

此时我们已经可以把整段的SQL语句取出,但还并没有在数据库中去执行,我们可以先来分析一下配置文件中SQL语句执行后的结果集是如何处理的。

Mybatis会将结果集按照映射配置文件中定义的映射规则,例如<resultMap>,resultType属性等,映射成相应的结果对象。

在StatementHandler接口执行完指定的select语句之后,会将查询得到的结果集交给ResultSetHandler完成映射处理。ResultSetHandler除了负责映射select语句查询得到的结果集,还会处理存储过程执行后的输出参数。ResultSetHandler是一个接口,定义如下

public interface ResultSetHandler {
  //处理结果集,生成相应的结果对象集合
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;
  //处理结果集,返回相应的游标对象
  <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
  //处理存储过程的输出参数
  void handleOutputParameters(CallableStatement cs) throws SQLException;

}

ResultSetHandler只有一个实现类DefaultResultSetHandler,其核心字段如下

private final Executor executor;  //执行器对象
private final Configuration configuration; //全局配置信息对象
private final MappedStatement mappedStatement; //记录了SQL语句节点所有信息的对象(<select><insert><update>节点等)
private final RowBounds rowBounds; //逻辑分页对象(不同于SQL语句中的limit物理分页)
private final ParameterHandler parameterHandler; //参数处理器
private final ResultHandler<?> resultHandler; //用户指定用于处理结果集的ResultHandler对象
private final BoundSql boundSql; //SqlSource执行后返回的包含完整SQL语句的对象
private final TypeHandlerRegistry typeHandlerRegistry; //类型处理器注册器
private final ObjectFactory objectFactory; //对象工厂
private final ReflectorFactory reflectorFactory; //反射工厂
private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>(); //嵌套的resultMap对象映射
private Object previousRowValue; //上一次嵌套的resultMap对象
//PendingRelation是DefaultResultSetHandler的内部静态类,记录了当前结果对象对应的MetaObject对象以及parentMapping对象
//该对象就为CacheKey对象跟全部的PendingRelation对象的映射
private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<CacheKey, List<PendingRelation>>();

通过select语句查询数据库得到的结果集由其handlerResultSets()方法进行处理。该方法不仅可以处理Statement,PreparedStatement产生的结果集,还可以处理CallableStatement调用存储过程产生的多结果集。例如如下存储过程,就会产生多个ResultSet对象。

CREATE PROCEDURE test_proc()

BEGIN

select * from persion;

select * from item;

END;

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;
  //获取第一个ResultSet对象,可能存在多个ResultSet
  ResultSetWrapper rsw = getFirstResultSet(stmt);
  //获取MappedStatement.resultMaps集合,映射文件中的<resultMap>节点会被解析成ResultMap对象,保存到MappedStatement.resultMaps集合中
  //如果SQL节点能够产生多个ResultSet,那么我们可以在SQL节点的resultMap属性中配置多个<resultMap>节点的id,它们之间通过","分隔,实现对多个
  //结果集的映射
  List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  int resultMapCount = resultMaps.size();
  //如果结果集不为null,则resultMaps集合(List)不能为空,否则抛出异常
  validateResultMapsCount(rsw, resultMapCount);
  //遍历resultMaps集合
  while (rsw != null && resultMapCount > resultSetCount) {
    //取出resultMaps集合中的每一个ResultMap对象
    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 ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
  //Statement是JDBC数据操作的接口,由Connection连接数据库后创建,由各种不同的数据库驱动来创建实现类,由于我们项目最近使用的是mysql 8版本的数据库,它的实现类已经跟
  //以往的mysql版本大不相同,此处为获取结果集
  ResultSet rs = stmt.getResultSet();
  while (rs == null) {
    // move forward to get the first resultset in case the driver
    // doesn't return the resultset as the first result (HSQLDB 2.1)
    //检测是否还有待处理的ResultSet
    if (stmt.getMoreResults()) {
      rs = stmt.getResultSet();
    } else {
      if (stmt.getUpdateCount() == -1) { //没有待处理的ResultSet
        // no more results. Must be no resultset
        break;
      }
    }
  }
  //将结果集封装成ResultSetWrapper对象
  return rs != null ? new ResultSetWrapper(rs, configuration) : null;
}
private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {
  if (rsw != null && resultMapCount < 1) {
    throw new ExecutorException("A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId()
        + "'.  It's likely that neither a Result Type nor a Result Map was specified.");
  }
}
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
  try {
    //如果ResultMapping对象不为null
    if (parentMapping != null) {
      handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
    } else {
      if (resultHandler == null) {
        DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
        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 {
  //该resultMap是否存在嵌套
  if (resultMap.hasNestedResultMaps()) {
    //确定没有分页,否则抛出异常
    ensureNoRowBounds();
    //确定没有结果集处理器,否则抛出异常
    checkResultHandler();
    handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  } else {
    handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  }
}
private void ensureNoRowBounds() {
  if (configuration.isSafeRowBoundsEnabled() && rowBounds != null && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET)) {
    throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "
        + "Use safeRowBoundsEnabled=false setting to bypass this check.");
  }
}
protected void checkResultHandler() {
  if (resultHandler != null && configuration.isSafeResultHandlerEnabled() && !mappedStatement.isResultOrdered()) {
    throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely used with a custom ResultHandler. "
        + "Use safeResultHandlerEnabled=false setting to bypass this check "
        + "or ensure your statement returns ordered data and set resultOrdered=true on it.");
  }
}
private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  //默认上下文对象
  final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
  //将结果集移动到分页处
  skipRows(rsw.getResultSet(), rowBounds);
  //获取上一次嵌套的resultMap对象
  Object rowValue = previousRowValue;
  //如果已处理的结果集还未到达上限且结果集中还有可以处理的记录,进入循环
  while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
    //获取所有嵌套中的最终resultMap对象
    final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
    //将该resultMap对象中的元素构建成CacheKey对象
    final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
    //从嵌套的resultMap映射中查找该CacheKey对象映射的resultMap对象
    Object partialObject = nestedResultObjects.get(rowKey);
    //如果<select>标签嵌套或者分组了
    if (mappedStatement.isResultOrdered()) {
      //如果嵌套映射中没有该resultMap对象且上一次嵌套的resultMap对象不为null
      if (partialObject == null && rowValue != null) {
        //清空嵌套resultMap映射
        nestedResultObjects.clear();
        //
        storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
      }
      rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
    } else {
      rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
      if (partialObject == null) {
        storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
      }
    }
  }
  if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
    storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    previousRowValue = null;
  } else if (rowValue != null) {
    previousRowValue = rowValue;
  }
}
private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
  //如果结果集的类型不为只前进类型
  if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
    //如果分页对象中有偏移量
    if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
      //将结果集对象定位到分页对象的偏移量处
      rs.absolute(rowBounds.getOffset());
    }
  //如果结果集的类型为只前进类型
  } else {
    //依次访问结果集直到分页对象的偏移量处
    for (int i = 0; i < rowBounds.getOffset(); i++) {
      rs.next();
    }
  }
}
private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
  //返回已经处理的行数是否到达分页的上限
  return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
}
public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
  //记录已经处理过的ResultMap的id
  Set<String> pastDiscriminators = new HashSet<String>();
  //获取<resultMap>中的<discriminator>节点对象,discriminator是一个鉴别器节点,以下有关于鉴别器节点的说明
  Discriminator discriminator = resultMap.getDiscriminator();
  //当该鉴别器对象不为null时,进入循环
  while (discriminator != null) {
    //获取记录中对应列的值,其中会使用相应的类型处理器对象将该列值转换成java类型
    final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
    //根据该列值获取对应的ResultMap的id,因为这里是处理嵌套的情况,所以在<discriminator>节点下又有<resultMap>节点,如果不嵌套就一般是
    //<result>或者<id>节点
    final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));
    //查找全局配置信息中是否有该嵌套的resultMap节点的id
    if (configuration.hasResultMap(discriminatedMapId)) {
      //如果有该id,根据该id在全局配置信息中获取该resultMap对象
      resultMap = configuration.getResultMap(discriminatedMapId);
      //记录当前鉴别器对象
      Discriminator lastDiscriminator = discriminator;
      //获取resultMap对象中的鉴别器对象
      discriminator = resultMap.getDiscriminator();
      //检测鉴别器是否出现了环形引用
      if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
        break;
      }
    } else {
      break;
    }
  }
  //返回所有嵌套中最终的使用的resultMap
  return resultMap;
}

鉴别器节点的说明

<!-- =======================鉴别器============================ --> <!-- <discriminator javaType=""></discriminator> 鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为 封装Employee: 如果查出的是女生:就把部门信息查询出来,否则不查询; 如果是男生,把last_name这一列的值赋值给email; --> <resultMap type="com.mybatis.bean.Employee" id="MyEmpDis"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- column:指定判定的列名 javaType:列值对应的java类型 --> <discriminator javaType="string" column="gender"> <!--女生 resultType:指定封装的结果类型;不能缺少。/resultMap--> <case value="0" resultType="com.atguigu.mybatis.bean.Employee"> <association property="dept" select="com.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </case> <!--男生 ;如果是男生,把last_name这一列的值赋值给email; --> <case value="1" resultType="com.mybatis.bean.Employee"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="last_name" property="email"/> <result column="gender" property="gender"/> </case> </discriminator> </resultMap>

private Object getDiscriminatorValue(ResultSet rs, Discriminator discriminator, String columnPrefix) throws SQLException {
  //获取鉴别器的resultMapping对象
  final ResultMapping resultMapping = discriminator.getResultMapping();
  //获取resultMapping对象的类型处理器对象
  final TypeHandler<?> typeHandler = resultMapping.getTypeHandler();
  //使用类型处理器来处理从全部结果集中获取columnPrefix+resultMapping.getColumn()为列名的Java对象
  return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
}
private String prependPrefix(String columnName, String prefix) {
  if (columnName == null || columnName.length() == 0 || prefix == null || prefix.length() == 0) {
    return columnName;
  }
  return prefix + columnName;
}
private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException {
  //创建CacheKey对象
  final CacheKey cacheKey = new CacheKey();
  //将resultMap的id作为Cachekey对象的一部分
  cacheKey.update(resultMap.getId());
  //查找ResultMapping对象集合
  List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);
  //如果该ResultMapping对象集合为空
  if (resultMappings.isEmpty()) {
    //如果ResultMap对象为Map接口的实现类
    if (Map.class.isAssignableFrom(resultMap.getType())) {
      //由结果集中的所有列名以及当前记录行的所有列值一起构成CacheKey对象
      createRowKeyForMap(rsw, cacheKey);
    //如果ResultMap对象不是Map接口的实现类
    } else {
      //由结果集中未映射的列名以及它们在当前记录中的对应列值一起构成CacheKey对象
      createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix);
    }
  //如果该ResultMapping对象集合不为空
  } else {
    //由resultMappings集合中的列名以及它们在当前记录行中相应的列值一起构成CacheKey
    createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix);
  }
  //如果通过上面的查找没有找到任何列参与构成CacheKey对象,则返回NULL_CACHE_KEY对象
  if (cacheKey.getUpdateCount() < 2) {
    return CacheKey.NULL_CACHE_KEY;
  }
  return cacheKey;
}
private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {
  //从resultMap对象中获取idResultMappings集合,该集合记录<idArg>、<id>节点对应的ResultMapping对象
  List<ResultMapping> resultMappings = resultMap.getIdResultMappings();
  //如果该集合为空
  if (resultMappings.isEmpty()) {
    //获取resultMap对象中记录了除<id*>节点之外的ResultMapping对象
    resultMappings = resultMap.getPropertyResultMappings();
  }
  return resultMappings;
}
private void createRowKeyForMap(ResultSetWrapper rsw, CacheKey cacheKey) throws SQLException {
  //获取结果集中的列名集合
  List<String> columnNames = rsw.getColumnNames();
  //遍历该集合
  for (String columnName : columnNames) {
    //获取结果集中每一列对应的值
    final String value = rsw.getResultSet().getString(columnName);
    //如果该值不为null
    if (value != null) {
      //将列名与值分别作为cacheKey的一部分
      cacheKey.update(columnName);
      cacheKey.update(value);
    }
  }
}
private void createRowKeyForUnmappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, String columnPrefix) throws SQLException {
  //获取resultMap对象的反射原类型对象(包含类所有的方法,属性,构造器等等)
  final MetaClass metaType = MetaClass.forClass(resultMap.getType(), reflectorFactory);
  //获取结果集的没有映射关系的列名集合
  List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
  //遍历该集合
  for (String column : unmappedColumnNames) {
    //获取每一个列名定为属性
    String property = column;
    //如果列前缀不为空
    if (columnPrefix != null && !columnPrefix.isEmpty()) {
      // When columnPrefix is specified, ignore columns without the prefix.
      //如果将每列转化为大写后以列前缀开头
      if (column.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
        //取出列前缀之后的字符串
        property = column.substring(columnPrefix.length());
      } else {
        continue;
      }
    }
    //如果ResultMap类中有该属性
    if (metaType.findProperty(property, configuration.isMapUnderscoreToCamelCase()) != null) {
      //从结果集中获取该列名对应的值
      String value = rsw.getResultSet().getString(column);
      //如果该值不为null
      if (value != null) {
        //将列名与值分别作为cacheKey的一部分
        cacheKey.update(column);
        cacheKey.update(value);
      }
    }
  }
}
private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix) throws SQLException {
  //遍历resultMappings集合
  for (ResultMapping resultMapping : resultMappings) {
    //如果resultMapping对象获取的嵌套ResultMap的id不为null而获取的结果集为null
    if (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null) {
      // Issue #392
      //从全局配置信息中获取该id对应的ResultMap对象
      final ResultMap nestedResultMap = configuration.getResultMap(resultMapping.getNestedResultMapId());
      //递归该嵌套ResultMap对象
      createRowKeyForMappedProperties(nestedResultMap, rsw, cacheKey, nestedResultMap.getConstructorResultMappings(),
          prependPrefix(resultMapping.getColumnPrefix(), columnPrefix));
    //如果resultMapping对象的嵌套查询id为null
    } else if (resultMapping.getNestedQueryId() == null) {
      //拼装columnPrefix+resultMapping.getColumn()为column字符串
      final String column = prependPrefix(resultMapping.getColumn(), columnPrefix);
      //获取resultMapping的类型处理器对象
      final TypeHandler<?> th = resultMapping.getTypeHandler();
      //获取结果集的映射列名集合
      List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
      // Issue #114
      //如果column不为null且列名集合中包含转换为大写的column
      if (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) {
        //通过类型处理器获取结果集中该column对应的Java对象(值)
        final Object value = th.getResult(rsw.getResultSet(), column);
        //如果该值不为null或者全局配置信息中允许返回空实例
        if (value != null || configuration.isReturnInstanceForEmptyRow()) {
          //将列名与值分别作为cacheKey的一部分
          cacheKey.update(column);
          cacheKey.update(value);
        }
      }
    }
  }
}
private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
  //如果上一层的ResultMapping对象不为null
  if (parentMapping != null) {
    //将嵌套对象记录到外层元对象相应的属性中
    linkToParents(rs, parentMapping, rowValue);
  //如果上一层的ResultMapping对象为null
  } else {
    callResultHandler(resultHandler, resultContext, rowValue);
  }
}

假设有这么一段resultMap

<resultMap id="blogResult" type="Blog"> <id property="id" column="id" /> <result property="title" column="title"/> <association property="author" javaType="Author" resultSet="authors" column="author_id" foreignColumn="id"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="email" column="email"/> <result property="bio" column="bio"/> </association> </resultMap>

private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException {
  //将外键对应结果集中的对象以及嵌套列名绑定到CacheKey对象中
  CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn());
  //获取该CacheKey对象对应的PendingRelation列表
  List<PendingRelation> parents = pendingRelations.get(parentKey);
  //如果该列表不为null
  if (parents != null) {
    //遍历该列表
    for (PendingRelation parent : parents) {
      //如果列表中的每一项不为null且上一次嵌套的resultMap对象也不为null
      if (parent != null && rowValue != null) {
        //将上一层嵌套的resultMap对象放入元数据类型对象的相应属性中,如果为集合则在集合属性中添加该rowValue;如果不为集合,则直接将该属性设置为rowValue
        linkObjects(parent.metaObject, parent.propertyMapping, rowValue);
      }
    }
  }
}
private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException {
  //新建CacheKey对象
  CacheKey cacheKey = new CacheKey();
  //将resultMapping对象绑定到cachekey中
  cacheKey.update(resultMapping);
  //如果该resultMapping的ForeignColumn属性和Column属性都不为null
  if (columns != null && names != null) {
    //以","为分隔符截取ForeignColumn为字符串数组
    String[] columnsArray = columns.split(",");
    //以","为分隔符截取Clounmn为字符串数组
    String[] namesArray = names.split(",");
    //遍历ForeignColumn字符串数组
    for (int i = 0; i < columnsArray.length; i++) {
      //获取字符串数组中的每一项在结果集中对象
      Object value = rs.getString(columnsArray[i]);
      //如果该对象不为null
      if (value != null) {
        //将Columns字符串数组中的每一项以及ForeignColumns中每一项对应结果集中的对象绑定到cachekey中
        cacheKey.update(namesArray[i]);
        cacheKey.update(value);
      }
    }
  }
  return cacheKey;
}
private void linkObjects(MetaObject metaObject, ResultMapping resultMapping, Object rowValue) {
  //检查上一层的resultMapping是否为集合,如果为集合则进行实例化返回
  final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);
  //如果返回的集合对象不为null
  if (collectionProperty != null) {
    //根据该集合对象在全局配置信息中生成元数据类型对象
    final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
    //元数据类型对象的对象包装器属性(集合)中添加上一层的resultMap对象
    targetMetaObject.add(rowValue);
  } else {
    //如果返回的集合对象为null,表示resultMapping对象不为集合,直接将上一层的resultMap对象设置进元数据对象的resultMapping.getProperty()属性中
    metaObject.setValue(resultMapping.getProperty(), rowValue);
  }
}
private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {
  //获取resultMapping对象的Property属性
  final String propertyName = resultMapping.getProperty();
  //从metaObject中获取resultMapping对象所对应的Java对象中该属性的值(metaObject与metaClass不同,metaClass保存了类的所有属性,方法;metaObject保存了对象所有属性
  //的值)
  Object propertyValue = metaObject.getValue(propertyName);
  //如果该值为null
  if (propertyValue == null) {
    //获取resultMapping对象的Java类实例
    Class<?> type = resultMapping.getJavaType();
    //如果该类实例为null(在配置文件中没写)
    if (type == null) {
      //从metaObject中获取该属性的Java类实例
      type = metaObject.getSetterType(propertyName);
    }
    try {
      //如果该java类实例为一个集合类型
      if (objectFactory.isCollection(type)) {
        //获取该集合类型的无参构造实例对象
        propertyValue = objectFactory.create(type);
        //将该对象设为元数据对象的属性的值
        metaObject.setValue(propertyName, propertyValue);
        //返回该对象
        return propertyValue;
      }
    } catch (Exception e) {
      throw new ExecutorException("Error instantiating collection property for result '" + resultMapping.getProperty() + "'.  Cause: " + e, e);
    }
  //如果该值不为null,且该值的类实例为集合类型
  } else if (objectFactory.isCollection(propertyValue.getClass())) {
    //返回该值
    return propertyValue;
  }
  return null;
}
private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
  resultContext.nextResultObject(rowValue);
  ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
}

在DefaultObjectFactory中

@Override
public <T> boolean isCollection(Class<T> type) {
  //返回type是否是Collection接口的实现类或子接口
  return Collection.class.isAssignableFrom(type);
}
@Override
public <T> T create(Class<T> type) {
  return create(type, null, null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
  //获取接口的实现类实例
  Class<?> classToCreate = resolveInterface(type);
  //返回该接口的实现类的实例化对象
  return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
protected Class<?> resolveInterface(Class<?> type) {
  //实现类
  Class<?> classToCreate;
  //如果该接口为List,Collection,Iterable
  if (type == List.class || type == Collection.class || type == Iterable.class) {
    //实现类定为ArrayList
    classToCreate = ArrayList.class;
  //如果该接口为Map
  } else if (type == Map.class) {
    //实现类定为HashMap
    classToCreate = HashMap.class;
  //如果该接口为SortedSet
  } else if (type == SortedSet.class) { // issue #510 Collections Support
    //实现类定为TreeSet
    classToCreate = TreeSet.class;
  //如果接口为Set
  } else if (type == Set.class) {
    //实现类定为HashSet
    classToCreate = HashSet.class;
  //如果不是集合接口
  } else {
    //直接获取该类
    classToCreate = type;
  }
  return classToCreate;
}
private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
  try {
    //定义构造器
    Constructor<T> constructor;
    //如果构造参数类型列表或者构造参数对象列表为null
    if (constructorArgTypes == null || constructorArgs == null) {
      //获取该类实例的无参构造器
      constructor = type.getDeclaredConstructor();
      //如果该构造器没有私有成员访问标志
      if (!constructor.isAccessible()) {
        //设置该构造器可以访问私有成员
        constructor.setAccessible(true);
      }
      //返回该构造器进行无参构造的对象实例
      return constructor.newInstance();
    }
    //如果构造参数类型列表或者构造参数对象列表不全为null,获取该类实例的以构造参数类型列表为构造参数的有参构造器
    constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
    if (!constructor.isAccessible()) {
      constructor.setAccessible(true);
    }
    //返回该构造器进行有参构造的对象实例
    return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
  } catch (Exception e) {
    //异常处理
    StringBuilder argTypes = new StringBuilder();
    if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
      for (Class<?> argType : constructorArgTypes) {
        argTypes.append(argType.getSimpleName());
        argTypes.append(",");
      }
      argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
    }
    StringBuilder argValues = new StringBuilder();
    if (constructorArgs != null && !constructorArgs.isEmpty()) {
      for (Object argValue : constructorArgs) {
        argValues.append(String.valueOf(argValue));
        argValues.append(",");
      }
      argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
    }
    throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
  }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档