Mybatis源码解析之DefaultResultSetHandler的handleResultSets方法解析

版权声明:感谢您的阅读,欢迎讨论并指出不足,可自由转载,但请注明出处和作者 https://blog.csdn.net/qq_39470742/article/details/88739032

Mybatis源码解析之核心类分析
Mybatis源码解析之初始化分析
Mybatis源码解析之执行流程解析
Mybatis源码解析之数据库连接和连接池
Mybatis源码解析之事务管理
Mybatis源码解析之缓存机制(一):一级缓存
Mybatis源码解析之缓存机制(二):二级缓存
Mybatis源码解析之插件机制
Mybatis源码解析之mapper接口的代理模式

ResultSetHandler是Mybatis的核心组件,主要负责将结果集resultSets转化成结果列表(或cursor)和处理储存过程的输出。
DefaultResultSetHandler是Myabtis为ResultSetHandler提供的唯一一个实现类,下面我们将深入DefaultResultSetHandler的源码了解其实如何转化结果集resultSet的。

一、ResultSetHandler

public interface ResultSetHandler {

 //将结果集转化成list
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;

//将结果集转化出呢个cursor
  <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

//处理存储过程的输出
  void handleOutputParameters(CallableStatement cs) throws SQLException;

}

二、handleResultSets方法解析

1. DefaultResultSetHandler#handleResultSets(Statement)

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);
     //根据resultMap处理rsw生成java对象
     handleResultSet(rsw, resultMap, multipleResults, null);
     //获取结果集的下一个结果
     rsw = getNextResultSet(stmt);
     cleanUpAfterHandlingResultSet();
     resultSetCount++;
   }

   String[] resultSets = mappedStatement.getResultSets();
   if (resultSets != null) {
   	//和resultMaps的遍历处理类似
     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 cleanUpAfterHandlingResultSet() {
  nestedResultObjects.clear();
}
//当list长度为1,表示该list的元素就是list类型的,返回元素即可。
@SuppressWarnings("unchecked")
private List<Object> collapseSingleResultList(List<Object> multipleResults) {
  return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
}

一般情况下,mappedStament中也只有一个resultMap,并不需要遍历。
额外提一点,即使我们在select的查询中配置的不是resultMap而是resultType,在mybatis中也是按照resultMap进行存储的。具体代码在MapperStatementAssistant#getSatementResultMaps(String, String, Class<?>, String)方法中,具体涉及到的代码如下:

else if (resultType != null) {
  ResultMap inlineResultMap = new ResultMap.Builder(
      configuration,
      statementId + "-Inline",
      resultType,
      new ArrayList<ResultMapping>(),
      null).build();
  resultMaps.add(inlineResultMap);
}

2. DefaultResultSetHandler#handleResultSet(ResultSetWrapper, ResultMap, List, ResultMapping)

ResultSet处理

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) {
        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());
  }
}

可以看到,虽然按照parentMapping和resultHandler分成了3种情况,但最终都进入了handleRowValues方法。

3. DefaultResultSetHandler#handleRowValue(ResultSetWrapper, ResultMap, ResultHandler, RowBounds, ResultMapping)

区分嵌套和不嵌套的处理

public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  if (resultMap.hasNestedResultMaps()) {
    ensureNoRowBounds();
    checkResultHandler();
    handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  } else {
    handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  }
}

可以看到,分成嵌套和不嵌套两种方法,进行处理,这里我们只管理不嵌套的处理,嵌套的虽然会比不嵌套复杂一点,但总体类似,差别并不大。

4. DefaultResultSetHandler#handleRowValueForSimpleMap(ResultSetWrapper, ResultMap, ResultHandler, RowBounds, ResultMapping)

分页处理并确定resultMap

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);
  while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
  //根据discriminate找到适合的ResultMap
    ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
    Object rowValue = getRowValue(rsw, discriminatedResultMap);
    storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
  }
}

//游标滑动,实现分页效果
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 void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
 if (parentMapping != null) {
    linkToParents(rs, parentMapping, rowValue);
  } else {
    callResultHandler(resultHandler, resultContext, rowValue);
  }
}
private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
  resultContext.nextResultObject(rowValue);
  ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
}

可以看出来核心逻辑实在Object rowValue = getRowValue(rsw, discriminatedResultMap);中。

5. DefaultResultSetHandler#getRowValue(ResultSetWrapper, ResultMap)

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
  final ResultLoaderMap lazyLoader = new ResultLoaderMap();
  Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
  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;
}

该方法生成了java对象,分3步
(1)createResultObject 生成对象
(2)applyAutomaticMappings 自动映射
(3)applyPropertyMappings property映射
这里还附带了ResultLoaderMap 的懒加载处理。

6 DefaultResultSetHandler#createResultObject(ResultSetWrapper, ResultMap, ResultLoadMap, String columnPrefix)

生成对象并处理嵌套查询的懒加载属性。懒加载本篇文章暂不分析。

private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
  this.useConstructorMappings = false; // reset previous mapping result
  final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
  final List<Object> constructorArgs = new ArrayList<Object>();
  //生成对象
  Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
  if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
    final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
    for (ResultMapping propertyMapping : propertyMappings) {
      // issue gcode #109 && issue #149
      //属性嵌套查询且懒加载
      if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
        resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
        break;
      }
    }
  }
  this.useConstructorMappings = (resultObject != null && !constructorArgTypes.isEmpty()); // set current mapping result
  return resultObject;
}

7 DefaultResultSetHandler#createResultObject(ResultSetWrapper, ResultMap, List<Class<?>>, List)

生成对象

private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
    throws SQLException {
  final Class<?> resultType = resultMap.getType();
  final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
  final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
  if (hasTypeHandlerForResultObject(rsw, resultType)) {
  //存在适用的typeHanlder类,事实上一般为基本数据类型或者其封装类
    return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
  } else if (!constructorMappings.isEmpty()) {
  //有参构造函数的constructor映射
    return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
  } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
  //接口或者无参构造函数
    return objectFactory.create(resultType);
  } else if (shouldApplyAutomaticMappings(resultMap, false)) {
  //有参构造函数的自动映射
    return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);
  }
  throw new ExecutorException("Do not know how to create an instance of " + resultType);
}

8. DefaultResultSetHandler#applyAutomaticMappings(ResultSetWrapper, ResultMap, MetaObject, String)

自动映射

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
//创建自动映射的映射对
  List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
  boolean foundValues = false;
  if (!autoMapping.isEmpty()) {
    for (UnMappedColumnAutoMapping mapping : autoMapping) {
      final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
      if (value != null) {
        foundValues = true;
      }
      if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
        // gcode issue #377, call setter on nulls (value is not 'found')
        metaObject.setValue(mapping.property, value);
      }
    }
  }
  return foundValues;
}

在启用自动映射的前提下,进行自动映射。
判断是否开启自动映射的条件:

private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
//resultMap配置了autoMapping = true
  if (resultMap.getAutoMapping() != null) {
    return resultMap.getAutoMapping();
  } else {
  //xml setting的属性autoMappingBehavior,有3个值:NONE(不启用),PARTIAL(不嵌套的时候启动),FULL(启动)
    if (isNested) {
      return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();
    } else {
      return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();
    }
  }
}

9. DefaultResultSetHandler#createAutomaticMappings(ResultSetWrapper, ResultMap, MetaObject, String)

找到自动映射对

private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  final String mapKey = resultMap.getId() + ":" + columnPrefix;
  //autoMappingsCache作为缓存,首先从缓存中获取
  List<UnMappedColumnAutoMapping> autoMapping = autoMappingsCache.get(mapKey);
  //缓存未命中
  if (autoMapping == null) {
    autoMapping = new ArrayList<UnMappedColumnAutoMapping>();
    final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
    for (String columnName : unmappedColumnNames) {
      String propertyName = columnName;
      if (columnPrefix != null && !columnPrefix.isEmpty()) {
        // When columnPrefix is specified,
        // ignore columns without the prefix.
        if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
          propertyName = columnName.substring(columnPrefix.length());
        } else {
          continue;
        }
      }
      //驼峰
      final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
      //存在set方法
      if (property != null && metaObject.hasSetter(property)) {
      //resultMap的应映射中已存在,忽略
        if (resultMap.getMappedProperties().contains(property)) {
          continue;
        }
        final Class<?> propertyType = metaObject.getSetterType(property);
        if (typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName))) {
          final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
          autoMapping.add(new UnMappedColumnAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive()));
        } else {
        //没找到,根据autoMappingUnknownColumnBehavior属性(默认为NONE)进行处理:NONE(忽略),WARNING(log.warn),ERROR(抛异常)
          configuration.getAutoMappingUnknownColumnBehavior()
              .doAction(mappedStatement, columnName, property, propertyType);
        }
      } else {
      // //没找到,根据autoMappingUnknownColumnBehavior属性(默认为NONE)进行处理:NONE(忽略),WARNING(log.warn),ERROR(抛异常)
        configuration.getAutoMappingUnknownColumnBehavior()
            .doAction(mappedStatement, columnName, (property != null) ? property : propertyName, null);
      }
    }
    //加入缓存
    autoMappingsCache.put(mapKey, autoMapping);
  }
  return autoMapping;
}

10. DefaultResultSetHandler#applyPropertyMappings(ResultSetWrapper, ResultMap, MetaObject, ResultLoaderMap, String)

resultmap的property映射

private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
    throws SQLException {
  final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
  boolean foundValues = false;
  final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
  for (ResultMapping propertyMapping : propertyMappings) {
    String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
    if (propertyMapping.getNestedResultMapId() != null) {
      // the user added a column attribute to a nested result map, ignore it
      //嵌套查询的属性,忽略column 
      column = null;
    }
    if (propertyMapping.isCompositeResult()
        || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
        || propertyMapping.getResultSet() != null) {
        //字段值
      Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
      // issue #541 make property optional
      final String property = propertyMapping.getProperty();
      if (property == null) {
        continue;
      } else if (value == DEFERED) {
        foundValues = true;
        continue;
      }
      if (value != null) {
        foundValues = true;
      }
      //赋值给对象
      if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {
        // gcode issue #377, call setter on nulls (value is not 'found')
        metaObject.setValue(property, value);
      }
    }
  }
  return foundValues;
}

三、handleResultSets流程

1. handleResultSets流程图

handleResultSets流程图

2. handleResultSet流程图

对于简单形式的ResultMap:
handleResultSet流程图

猜你喜欢

转载自blog.csdn.net/qq_39470742/article/details/88739032