Mybatis源码分析之结果封装ResultSetHandler和DefaultResultSetHandler

来源:互联网 发布:js判断对象是否为null 编辑:程序博客网 时间:2024/06/04 18:51
ResultSetHandler负责处理两件事:
(1)处理Statement执行后产生的结果集,生成结果列表
(2)处理存储过程执行后的输出参数
ResultSetHandler是一个接口,提供了两个函数分别用来处理普通操作和存储过程的结果,
源码如下:
/** * @author Clinton Begin */public interface ResultSetHandler {  <E> List<E> handleResultSets(Statement stmt) throws SQLException;  void handleOutputParameters(CallableStatement cs) throws SQLException;}

ResultSetHandler的具体实现类是DefaultResultSetHandler,其实现的步骤就是将Statement执行后的结果集,按照Mapper文件中配置的ResultType或ResultMap来封装成对应的对象,最后将封装的对象返回即可,
DefaultResultSetHandler源码如下:

//ResultSetHandler具体实现类public class DefaultResultSetHandler implements ResultSetHandler {  private static final Object DEFERED = new Object();  private final Executor executor;  private final Configuration configuration;  private final MappedStatement mappedStatement;  private final RowBounds rowBounds;  private final ParameterHandler parameterHandler;  private final ResultHandler<?> resultHandler;  private final BoundSql boundSql;  private final TypeHandlerRegistry typeHandlerRegistry;  private final ObjectFactory objectFactory;  private final ReflectorFactory reflectorFactory;  // nested resultmaps  // 此Map用来保存当前层级内部的结果对象(一对多关系的多方对象),key为combinedKey  private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();  // 此Map用来保存当前层级的根对象(一对多关系中的一方对象),key为absoluteKey  private final Map<CacheKey, Object> ancestorObjects = new HashMap<CacheKey, Object>();  private final Map<String, String> ancestorColumnPrefix = new HashMap<String, String>();  // multiple resultsets  private final Map<String, ResultMapping> nextResultMaps = new HashMap<String, ResultMapping>();  private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<CacheKey, List<PendingRelation>>();  private static class PendingRelation {    public MetaObject metaObject;    public ResultMapping propertyMapping;  }  public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql,      RowBounds rowBounds) {    this.executor = executor;    this.configuration = mappedStatement.getConfiguration();    this.mappedStatement = mappedStatement;    this.rowBounds = rowBounds;    this.parameterHandler = parameterHandler;    this.boundSql = boundSql;    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();    this.objectFactory = configuration.getObjectFactory();    this.reflectorFactory = configuration.getReflectorFactory();    this.resultHandler = resultHandler;  }  //  // HANDLE OUTPUT PARAMETER  //  //调用存储过程返回结果,将结果值放在参数中  @Override  public void handleOutputParameters(CallableStatement cs) throws SQLException {    final Object parameterObject = parameterHandler.getParameterObject();    final MetaObject metaParam = configuration.newMetaObject(parameterObject);    final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();//循环处理每个参数    for (int i = 0; i < parameterMappings.size(); i++) {      final ParameterMapping parameterMapping = parameterMappings.get(i);  //判断参数的模式      if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {        if (ResultSet.class.equals(parameterMapping.getJavaType())) {          handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);        } else {          final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();          metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));        }      }    }  }  private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException {    try {      final String resultMapId = parameterMapping.getResultMapId();      final ResultMap resultMap = configuration.getResultMap(resultMapId);      final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory);      final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration);      handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);      metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList());    } finally {      // issue #228 (close resultsets)      closeResultSet(rs);    }  }  //  // HANDLE RESULT SETS  //  //对普通查询到的结果转换  @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 rsw = getFirstResultSet(stmt);//获得resultMap    List<ResultMap> resultMaps = mappedStatement.getResultMaps();//这边应该为1吧,一般resultMap为一个    int resultMapCount = resultMaps.size();//判断是否有resultMap,没有的话抛出异常    validateResultMapsCount(rsw, resultMapCount);    while (rsw != null && resultMapCount > resultSetCount) {  //获得resultMap,实体类和表中数据字段的对应关系      ResultMap resultMap = resultMaps.get(resultSetCount);  //将值设置成对应的resultmap对象      handleResultSet(rsw, resultMap, multipleResults, null);      rsw = getNextResultSet(stmt);      cleanUpAfterHandlingResultSet();      resultSetCount++;    }    String[] resultSets = mappedStatement.getResulSets();    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 {    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)      if (stmt.getMoreResults()) {        rs = stmt.getResultSet();      } else {        if (stmt.getUpdateCount() == -1) {          // no more results. Must be no resultset          break;        }      }    }//将数据打包    return rs != null ? new ResultSetWrapper(rs, configuration) : null;  }//获取下一个值,将值打包  private ResultSetWrapper getNextResultSet(Statement stmt) throws SQLException {    // Making this method tolerant of bad JDBC drivers    try {      if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {        // Crazy Standard JDBC way of determining if there are more results        if (!((!stmt.getMoreResults()) && (stmt.getUpdateCount() == -1))) {          ResultSet rs = stmt.getResultSet();          return rs != null ? new ResultSetWrapper(rs, configuration) : null;        }      }    } catch (Exception e) {      // Intentionally ignored.    }    return null;  }//关闭resultSet  private void closeResultSet(ResultSet rs) {    try {      if (rs != null) {        rs.close();      }    } catch (SQLException e) {      // ignore    }  }  private void cleanUpAfterHandlingResultSet() {    nestedResultObjects.clear();    ancestorColumnPrefix.clear();  }    //校验结果的resultMap,如果没有的话就抛出异常  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 {      if (parentMapping != null) {        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);      } else {        if (resultHandler == null) {// 创建一个新对象          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);  //将查询到的每个字段和Bean实体中的属性对应起来,生成一个Result对象          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);  //结果映射对象及值添加到multipleResults中          multipleResults.add(defaultResultHandler.getResultList());        } else {          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);        }      }    } finally {      // issue #228 (close resultsets)      closeResultSet(rsw.getResultSet());    }  }  @SuppressWarnings("unchecked")  private List<Object> collapseSingleResultList(List<Object> multipleResults) {    return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;  }  //  // HANDLE ROWS FOR SIMPLE RESULTMAP  ////操作列值  private 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);    }  } //判断记录行数  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 handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)      throws SQLException {    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();//跳过RowBounds设置的offset值    skipRows(rsw.getResultSet(), rowBounds);//判断数据是否小于limit,如果小于limit的话就不断的循环取值    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);      Object rowValue = getRowValue(rsw, discriminatedResultMap);      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());    }  }  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);    }  }  @SuppressWarnings("unchecked" /* because ResultHandler<?> is always ResultHandler<Object>*/)  private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {    resultContext.nextResultObject(rowValue);    ((ResultHandler<Object>)resultHandler).handleResult(resultContext);  }  private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {//判断数据是否小于limit,小于返回true    return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();  }  //跳过不需要的行,应该就是rowbounds设置的limit和offset  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 {  //跳过RowBounds中设置的offset条数据      for (int i = 0; i < rowBounds.getOffset(); i++) {        rs.next();      }    }  }  //  // GET VALUE FROM ROW FOR SIMPLE RESULT MAP  //  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {    final ResultLoaderMap lazyLoader = new ResultLoaderMap();//结果的映射对象    Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {      final MetaObject metaObject = configuration.newMetaObject(resultObject);      boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();      if (shouldApplyAutomaticMappings(resultMap, false)) {        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;      }      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;      foundValues = lazyLoader.size() > 0 || foundValues;      resultObject = foundValues ? resultObject : null;      return resultObject;    }    return resultObject;  }//用于判断是否是bean实体变量和表中字段自动映射  private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {    if (resultMap.getAutoMapping() != null) {      return resultMap.getAutoMapping();    } else {      if (isNested) {        return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();      } else {        return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();      }    }  }  //  // PROPERTY MAPPINGS  //  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 = 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();        // issue #377, call setter on nulls        if (value != DEFERED            && property != null            && (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()))) {          metaObject.setValue(property, value);        }        if (value != null || value == DEFERED) {          foundValues = true;        }      }    }    return foundValues;  }  private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)      throws SQLException {    if (propertyMapping.getNestedQueryId() != null) {      return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);    } else if (propertyMapping.getResultSet() != null) {      addPendingChildRelation(rs, metaResultObject, propertyMapping);   // TODO is that OK?      return DEFERED;    } else {      final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();      final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);      return typeHandler.getResult(rs, column);    }  }  //  private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {    final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);    boolean foundValues = false;//获得列名    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());      if (property != null && metaObject.hasSetter(property)) {        final Class<?> propertyType = metaObject.getSetterType(property);        if (typeHandlerRegistry.hasTypeHandler(propertyType)) {          final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);          final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);          // issue #377, call setter on nulls          if (value != null || configuration.isCallSettersOnNulls()) {            if (value != null || !propertyType.isPrimitive()) {              metaObject.setValue(property, value);            }            foundValues = true;          }        }      }    }    return foundValues;  }  // MULTIPLE RESULT SETS  private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException {    CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn());    List<PendingRelation> parents = pendingRelations.get(parentKey);    if (parents != null) {      for (PendingRelation parent : parents) {        if (parent != null && rowValue != null) {            linkObjects(parent.metaObject, parent.propertyMapping, rowValue);        }      }    }  }  private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject, ResultMapping parentMapping) throws SQLException {    CacheKey cacheKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getColumn());    PendingRelation deferLoad = new PendingRelation();    deferLoad.metaObject = metaResultObject;    deferLoad.propertyMapping = parentMapping;    List<PendingRelation> relations = pendingRelations.get(cacheKey);    // issue #255    if (relations == null) {      relations = new ArrayList<DefaultResultSetHandler.PendingRelation>();      pendingRelations.put(cacheKey, relations);    }    relations.add(deferLoad);    ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet());    if (previous == null) {      nextResultMaps.put(parentMapping.getResultSet(), parentMapping);    } else {      if (!previous.equals(parentMapping)) {        throw new ExecutorException("Two different properties are mapped to the same resultSet");      }    }  }  private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException {    CacheKey cacheKey = new CacheKey();    cacheKey.update(resultMapping);    if (columns != null && names != null) {      String[] columnsArray = columns.split(",");      String[] namesArray = names.split(",");      for (int i = 0 ; i < columnsArray.length ; i++) {        Object value = rs.getString(columnsArray[i]);        if (value != null) {          cacheKey.update(namesArray[i]);          cacheKey.update(value);        }      }    }    return cacheKey;  }  //  // INSTANTIATION & CONSTRUCTOR MAPPING  //  //创建结果对象  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {    final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();    final List<Object> constructorArgs = new ArrayList<Object>();//结果对象    final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {//获取配置的resultMap的字段与表中数据的映射关系      final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();      for (ResultMapping propertyMapping : propertyMappings) {        // issue gcode #109 && issue #149        if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {          return configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);        }      }    }    return resultObject;  }  //创建结果对象  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 (typeHandlerRegistry.hasTypeHandler(resultType)) {//基本类型      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);    } else if (!constructorMappings.isEmpty()) {//有参数构造函数      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {//普通的bean类型      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);  }//有参数构造函数  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);        } else {          final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler();          value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix));        }      } catch (ResultMapException e) {        throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);      } catch (SQLException e) {        throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);      }      constructorArgTypes.add(parameterType);      constructorArgs.add(value);      foundValues = value != null || foundValues;    }    return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;  }//自动映射  private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs,      String columnPrefix) throws SQLException {    for (Constructor<?> constructor : resultType.getDeclaredConstructors()) {      if (typeNames(constructor.getParameterTypes()).equals(rsw.getClassNames())) {        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(), prependPrefix(columnName, columnPrefix));          constructorArgTypes.add(parameterType);          constructorArgs.add(value);          foundValues = value != null || foundValues;        }        return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;      }    }    throw new ExecutorException("No constructor found in " + resultType.getName() + " matching " + rsw.getClassNames());  }  private List<String> typeNames(Class<?>[] parameterTypes) {    List<String> names = new ArrayList<String>();    for (Class<?> type : parameterTypes) {      names.add(type.getName());    }    return names;  }//创建原型结果  private Object createPrimitiveResultObject(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {    final Class<?> resultType = resultMap.getType();    final String columnName;    if (!resultMap.getResultMappings().isEmpty()) {      final List<ResultMapping> resultMappingList = resultMap.getResultMappings();      final ResultMapping mapping = resultMappingList.get(0);      columnName = prependPrefix(mapping.getColumn(), columnPrefix);    } else {      columnName = rsw.getColumnNames().get(0);    }    final TypeHandler<?> typeHandler = rsw.getTypeHandler(resultType, columnName);    return typeHandler.getResult(rsw.getResultSet(), columnName);  }  //  // NESTED QUERY  //  private Object getNestedQueryConstructorValue(ResultSet rs, ResultMapping constructorMapping, String columnPrefix) throws SQLException {    final String nestedQueryId = constructorMapping.getNestedQueryId();    final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);    final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();    final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, constructorMapping, nestedQueryParameterType, columnPrefix);    Object value = null;    if (nestedQueryParameterObject != null) {      final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);      final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);      final Class<?> targetType = constructorMapping.getJavaType();      final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);      value = resultLoader.loadResult();    }    return value;  }//得到嵌套查询值  private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)      throws SQLException {    final String nestedQueryId = propertyMapping.getNestedQueryId();    final String property = propertyMapping.getProperty();    final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);    final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();    final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);    Object value = null;    if (nestedQueryParameterObject != null) {      final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);      final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);      final Class<?> targetType = propertyMapping.getJavaType();      if (executor.isCached(nestedQuery, key)) {//如果已经有一级缓存了,则延迟加载(实际上deferLoad方法中可以看到则是立即加载)        executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);        value = DEFERED;      } else {//否则lazyLoader.addLoader 需要延迟加载则addLoader    //或者ResultLoader.loadResult 不需要延迟加载则立即加载        final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);        if (propertyMapping.isLazy()) {          lazyLoader.addLoader(property, metaResultObject, resultLoader);          value = DEFERED;        } else {          value = resultLoader.loadResult();        }      }    }    return value;  }  private Object prepareParameterForNestedQuery(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {    if (resultMapping.isCompositeResult()) {      return prepareCompositeKeyParameter(rs, resultMapping, parameterType, columnPrefix);    } else {      return prepareSimpleKeyParameter(rs, resultMapping, parameterType, columnPrefix);    }  }  private Object prepareSimpleKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {    final TypeHandler<?> typeHandler;    if (typeHandlerRegistry.hasTypeHandler(parameterType)) {      typeHandler = typeHandlerRegistry.getTypeHandler(parameterType);    } else {      typeHandler = typeHandlerRegistry.getUnknownTypeHandler();    }    return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));  }  private Object prepareCompositeKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {    final Object parameterObject = instantiateParameterObject(parameterType);    final MetaObject metaObject = configuration.newMetaObject(parameterObject);    boolean foundValues = false;    for (ResultMapping innerResultMapping : resultMapping.getComposites()) {      final Class<?> propType = metaObject.getSetterType(innerResultMapping.getProperty());      final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propType);      final Object propValue = typeHandler.getResult(rs, prependPrefix(innerResultMapping.getColumn(), columnPrefix));      // issue #353 & #560 do not execute nested query if key is null      if (propValue != null) {        metaObject.setValue(innerResultMapping.getProperty(), propValue);        foundValues = true;      }    }    return foundValues ? parameterObject : null;  }  private Object instantiateParameterObject(Class<?> parameterType) {    if (parameterType == null) {      return new HashMap<Object, Object>();    } else {      return objectFactory.create(parameterType);    }  }  //  // DISCRIMINATOR //  public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {    Set<String> pastDiscriminators = new HashSet<String>();    Discriminator discriminator = resultMap.getDiscriminator();    while (discriminator != null) {      final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);      final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));      if (configuration.hasResultMap(discriminatedMapId)) {        resultMap = configuration.getResultMap(discriminatedMapId);        Discriminator lastDiscriminator = discriminator;        discriminator = resultMap.getDiscriminator();        if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {          break;        }      } else {        break;      }    }    return resultMap;  }  private Object getDiscriminatorValue(ResultSet rs, Discriminator discriminator, String columnPrefix) throws SQLException {    final ResultMapping resultMapping = discriminator.getResultMapping();    final TypeHandler<?> typeHandler = resultMapping.getTypeHandler();    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;  }  //  // HANDLE NESTED RESULT MAPS  //  //生成嵌套对象值  private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {    //创建默认结果上下文final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();    //跳过rowBounds指定offset行偏移量skipRows(rsw.getResultSet(), rowBounds);    Object rowValue = null;//如何定义应该处理:上下文没有主动停止,结果集还有记录,且上下文中结果对象数量不足时,应该继续处理    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {     // 解决鉴别过的结果映射,逻辑如下:     // 获取结果映射中的鉴别器,通过鉴别指定字段通过配置对象获取对应的另一个结果映射,循环往复,     // 直到找不到鉴别器为止,返回最终的结果映射 final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);      // 创建缓存key,如何创建?  final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);      // 缓存中获取结果对象  Object partialObject = nestedResultObjects.get(rowKey);      // issue #577 && #542      if (mappedStatement.isResultOrdered()) {        if (partialObject == null && rowValue != null) {          nestedResultObjects.clear();  // 保存结果对象          storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());        }// 获取行值        rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);      } else {        rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, 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());    }  }  //  // GET VALUE FROM ROW FOR NESTED RESULT MAP  //   //  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, Object partialObject) throws SQLException {    final String resultMapId = resultMap.getId();    Object resultObject = partialObject;    if (resultObject != null) {      final MetaObject metaObject = configuration.newMetaObject(resultObject);      putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);      applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);      ancestorObjects.remove(absoluteKey);    } else {      final ResultLoaderMap lazyLoader = new ResultLoaderMap();      resultObject = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);      if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {        final MetaObject metaObject = configuration.newMetaObject(resultObject);        boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();        if (shouldApplyAutomaticMappings(resultMap, true)) {          foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;        }        foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;        putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);        foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;        ancestorObjects.remove(absoluteKey);        foundValues = lazyLoader.size() > 0 || foundValues;        resultObject = foundValues ? resultObject : null;      }      if (combinedKey != CacheKey.NULL_CACHE_KEY) {        nestedResultObjects.put(combinedKey, resultObject);      }    }    return resultObject;  }  private void putAncestor(CacheKey rowKey, Object resultObject, String resultMapId, String columnPrefix) {    if (!ancestorColumnPrefix.containsKey(resultMapId)) {      ancestorColumnPrefix.put(resultMapId, columnPrefix);    }    ancestorObjects.put(rowKey, resultObject);  }  //  // NESTED RESULT MAP (JOIN MAPPING)  //  private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {    boolean foundValues = false;    for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {      final String nestedResultMapId = resultMapping.getNestedResultMapId();      if (nestedResultMapId != null && resultMapping.getResultSet() == null) {        try {          final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);          final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);          CacheKey rowKey = null;          Object ancestorObject = null;          if (ancestorColumnPrefix.containsKey(nestedResultMapId)) {            rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId));            ancestorObject = ancestorObjects.get(rowKey);          }          if (ancestorObject != null) {            if (newObject) {              linkObjects(metaObject, resultMapping, ancestorObject); // issue #385            }          } else {            rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);            final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);            Object rowValue = nestedResultObjects.get(combinedKey);            boolean knownValue = (rowValue != null);            instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory                        if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) {              rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue);              if (rowValue != null && !knownValue) {                linkObjects(metaObject, resultMapping, rowValue);                foundValues = true;              }            }          }        } catch (SQLException e) {          throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'.  Cause: " + e, e);        }      }    }    return foundValues;  }  private String getColumnPrefix(String parentPrefix, ResultMapping resultMapping) {    final StringBuilder columnPrefixBuilder = new StringBuilder();    if (parentPrefix != null) {      columnPrefixBuilder.append(parentPrefix);    }    if (resultMapping.getColumnPrefix() != null) {      columnPrefixBuilder.append(resultMapping.getColumnPrefix());    }    return columnPrefixBuilder.length() == 0 ? null : columnPrefixBuilder.toString().toUpperCase(Locale.ENGLISH);  }  private boolean anyNotNullColumnHasValue(ResultMapping resultMapping, String columnPrefix, ResultSet rs) throws SQLException {    Set<String> notNullColumns = resultMapping.getNotNullColumns();    boolean anyNotNullColumnHasValue = true;    if (notNullColumns != null && !notNullColumns.isEmpty()) {      anyNotNullColumnHasValue = false;      for (String column: notNullColumns) {        rs.getObject(prependPrefix(column, columnPrefix));        if (!rs.wasNull()) {          anyNotNullColumnHasValue = true;          break;        }      }    }    return anyNotNullColumnHasValue;  }  private ResultMap getNestedResultMap(ResultSet rs, String nestedResultMapId, String columnPrefix) throws SQLException {    ResultMap nestedResultMap = configuration.getResultMap(nestedResultMapId);    return resolveDiscriminatedResultMap(rs, nestedResultMap, columnPrefix);  }  //  // UNIQUE RESULT KEY  //  private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException {    final CacheKey cacheKey = new CacheKey();    cacheKey.update(resultMap.getId());    List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);    if (resultMappings.size() == 0) {      if (Map.class.isAssignableFrom(resultMap.getType())) {        createRowKeyForMap(rsw, cacheKey);      } else {        createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix);      }    } else {      createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix);    }    return cacheKey;  }  private CacheKey combineKeys(CacheKey rowKey, CacheKey parentRowKey) {    if (rowKey.getUpdateCount() > 1 && parentRowKey.getUpdateCount() > 1) {      CacheKey combinedKey;      try {        combinedKey = rowKey.clone();      } catch (CloneNotSupportedException e) {        throw new ExecutorException("Error cloning cache key.  Cause: " + e, e);      }      combinedKey.update(parentRowKey);      return combinedKey;    }    return CacheKey.NULL_CACHE_KEY;  }  private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {    List<ResultMapping> resultMappings = resultMap.getIdResultMappings();    if (resultMappings.size() == 0) {      resultMappings = resultMap.getPropertyResultMappings();    }    return resultMappings;  }  private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix) throws SQLException {    for (ResultMapping resultMapping : resultMappings) {      if (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null) {        // Issue #392        final ResultMap nestedResultMap = configuration.getResultMap(resultMapping.getNestedResultMapId());        createRowKeyForMappedProperties(nestedResultMap, rsw, cacheKey, nestedResultMap.getConstructorResultMappings(),            prependPrefix(resultMapping.getColumnPrefix(), columnPrefix));      } else if (resultMapping.getNestedQueryId() == null) {        final String column = prependPrefix(resultMapping.getColumn(), columnPrefix);        final TypeHandler<?> th = resultMapping.getTypeHandler();        List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);        // Issue #114        if (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) {          final Object value = th.getResult(rsw.getResultSet(), column);          if (value != null) {            cacheKey.update(column);            cacheKey.update(value);          }        }      }    }  }  private void createRowKeyForUnmappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, String columnPrefix) throws SQLException {    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;        }      }      if (metaType.findProperty(property, configuration.isMapUnderscoreToCamelCase()) != null) {        String value = rsw.getResultSet().getString(column);        if (value != null) {          cacheKey.update(column);          cacheKey.update(value);        }      }    }  }  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);      if (value != null) {        cacheKey.update(columnName);        cacheKey.update(value);      }    }  }  private void linkObjects(MetaObject metaObject, ResultMapping resultMapping, Object rowValue) {    final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);    if (collectionProperty != null) {      final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);      targetMetaObject.add(rowValue);    } else {      metaObject.setValue(resultMapping.getProperty(), rowValue);    }  }  private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {    final String propertyName = resultMapping.getProperty();    Object propertyValue = metaObject.getValue(propertyName);    if (propertyValue == null) {      Class<?> type = resultMapping.getJavaType();      if (type == null) {        type = metaObject.getSetterType(propertyName);      }      try {        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);      }    } else if (objectFactory.isCollection(propertyValue.getClass())) {      return propertyValue;    }    return null;  }}


1 0
原创粉丝点击