Mybatis核心处理层-ResultHandler参数映射核心逻辑-2

结果集映射/简单映射/自动映射

Posted by Claire on July 16, 2020

ResultSetHandler 参数映射核心逻辑 -2

一、简单映射

  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 defaultResultHandler = new DefaultResultHandler(objectFactory);
          //处理映射,将结果对象添加到defaultResultHandler
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          //将defaultResultHandler中结果添加到multiResults
          multipleResults.add(defaultResultHandler.getResultList());
        } else {
          //使用用户指定的结果集处理器进行处理
          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
        }
      }
    } finally {
      // issue #228 (close resultsets)
      closeResultSet(rsw.getResultSet());
    }
  }

1.无论是多结果集、未指定resulthandler 或 指定resultHandler 都会调用handleRowValues 作为入口

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

2.handleRowValuesForSimpleResultMap 处理简单映射

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
    ResultSet resultSet = rsw.getResultSet();
    //1 找到指定Offset行
    skipRows(resultSet, rowBounds);
    //判断是否处理行数达到上线
    while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
      //解析ResultMap
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
      //获取ResultSet中的记录
      Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
      //存储结果对象,放入ResultHanlder的resultlIST中
      storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
    }
  }

  • skipRows
  //skipRows
    private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
    //判断resultMap类型
    if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
      if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
        //直接定位到offset未知
        rs.absolute(rowBounds.getOffset());
      }
    } else {
      //多次调用到offset的位置
      for (int i = 0; i < rowBounds.getOffset(); i++) {
        if (!rs.next()) {
          break;
        }
      }
    }
  }

  • shouldProcessMoreRows
//shouldProcessMoreRows
  private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) {
    //检测DefaultResultContext的stopped字段,结果集数量小于RowBounds.limit
    return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
  }
  • resolveDiscriminatedResultMap
  //resolveDiscriminatedResultMap
   public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
    //记录处理过得ResultMap id
    Set<String> pastDiscriminators = new HashSet<>();
    //获取 Discriminator 对象
    Discriminator discriminator = resultMap.getDiscriminator();
    while (discriminator != null) {
      //获取Discriminator 的值
      final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
      //查找mapId
      final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));
      if (configuration.hasResultMap(discriminatedMapId)) {
        //存在resultMap
        resultMap = configuration.getResultMap(discriminatedMapId);
        //记录当前Discriminator 对象
        Discriminator lastDiscriminator = discriminator;
        discriminator = resultMap.getDiscriminator();
        //判断不是环形引用
        if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
          break;
        }
      } else {
        break;
      }
    }
    return resultMap;
  }
  • getRowValue
  //getRowValue
    private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
    //延迟加载
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    //1. 创建该行记录映射后得到的结果对象,该对象的类型由resultMap的type决定
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      //创建相应的MetaObject对象
      final MetaObject metaObject = configuration.newMetaObject(rowValue);
      // foundValues--true 成功映射任意属性;foundValues--false 未成功映射所有属性
      boolean foundValues = this.useConstructorMappings;
      //检测是否进行自动映射
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        //2.自动映射未明确指定的列
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
      }
      //3.映射明确的列
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      //如果没有成功映射任务属性,则根据mybatis-config.xml中的 rreturnInstanceForEmptyRow 决定是否返回空对象或者null
      rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
    }
    return rowValue;
  }
  • createResultObject
 // createResultObject 的最终方法
  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    //获取ResultMap中记录的type属性,也就是该行记录最终映射成的结果对象类型
    final Class<?> resultType = resultMap.getType();
    //
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
    //获取constrcutor节点
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (hasTypeHandlerForResultObject(rsw, resultType)) {
      //1.存在类型处理器
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (!constructorMappings.isEmpty()) {
      //2.存在constructor节点
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
      //3.是接口,或者有默认无参构造函数
      return objectFactory.create(resultType);
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
      //4.不是嵌套的,开启自动映射 ,查找何时的构造函数,并创建结果对象
      return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs);
    }
    //抛出异常
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
  }
  • createParameterizedResultObject
Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType, List<ResultMapping> constructorMappings,
                                         List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) {
    boolean foundValues = false;
    //遍历构造函数参数
    for (ResultMapping constructorMapping : constructorMappings) {
      //构造参数类型
      final Class<?> parameterType = constructorMapping.getJavaType();
      final String column = constructorMapping.getColumn();
      final Object value;
      try {
        if (constructorMapping.getNestedQueryId() != null) {
          value = getNestedQueryConstructorValue(rsw.getResultSet(), constructorMapping, columnPrefix);
        } else if (constructorMapping.getNestedResultMapId() != null) {
          final ResultMap resultMap = configuration.getResultMap(constructorMapping.getNestedResultMapId());
          value = getRowValue(rsw, resultMap, getColumnPrefix(columnPrefix, constructorMapping));
        } else {
          //获取 TypeHandler 直接获取结果
          final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler();
          value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix));
        }
      } catch (ResultMapException | SQLException e) {
        throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);
      }
      //记录参数类型
      constructorArgTypes.add(parameterType);
      //记录参数实际值
      constructorArgs.add(value);
      foundValues = value != null || foundValues;
    }
    // objectFactory.create 创建对象
    return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
  }
  • createByConstructorSignature
  private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) throws SQLException {
    //查找构造函数
    final Constructor<?>[] constructors = resultType.getDeclaredConstructors();
    //查找默认无参构造函数
    final Constructor<?> defaultConstructor = findDefaultConstructor(constructors);
    if (defaultConstructor != null) {
      //存在无参构造
      return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, defaultConstructor);
    } else {
      //不存在无参构造
      for (Constructor<?> constructor : constructors) {
        if (allowedConstructorUsingTypeHandlers(constructor, rsw.getJdbcTypes())) {
          //存在对应类型的类型处理器
          return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, constructor);
        }
      }
    }
    throw new ExecutorException("No constructor found in " + resultType.getName() + " matching " + rsw.getClassNames());
  }
  • createUsingConstructor 通过constructor创建结果对象
  private Object createUsingConstructor(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, Constructor<?> constructor) throws SQLException {
    boolean foundValues = false;
    for (int i = 0; i < constructor.getParameterTypes().length; i++) {
      //获取参数类型
      Class<?> parameterType = constructor.getParameterTypes()[i];
      //参数名称
      String columnName = rsw.getColumnNames().get(i);
      //获取类型处理器
      TypeHandler<?> typeHandler = rsw.getTypeHandler(parameterType, columnName);
      //获取实际值
      Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
      //添加处理过得类型
      constructorArgTypes.add(parameterType);
      //添加处理过的值
      constructorArgs.add(value);
      foundValues = value != null || foundValues;
    }
    //创建结果对象  objectFactory.create
    return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
  }
  • shouldApplyAutomaticMappings 是否使用自动映射
  private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
    //resultMap 配置autoMapping
    if (resultMap.getAutoMapping() != null) {
      return resultMap.getAutoMapping();
    } else {
      if (isNested) {
        //是嵌套的情况,settings --AutoMappingBehavior 配置FULL
        return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();
      } else {
        //不是嵌套情况,settings -- AutoMappingBehavior 配置不是NONE即可
        return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();
      }
    }
  }

  • applyAutomaticMappings 自动映射逻辑
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;
  }
  • applyPropertyMappings 处理明确参数映射的
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
        //该属性需要使用一个嵌套ResultMap进行映射,忽略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 == DEFERRED) {
          // DEFERRED 标识占位符对象
          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;
  }

  • storeObject
  //storeObject
    //存储结果对象,如果是嵌套子类,就将结果存储到父类的属性中,如果是普通映射,就存储到ResultHandler中
  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);
    }
  }