Skip to content

MyBatis结果集处理 ​

深入理解MyBatis结果集的处理机制,掌握结果集的映射和对象创建,理解类型处理、延迟加载等核心功能。

📋 结果集处理概览 ​

结果集处理是MyBatis将数据库结果集转换为Java对象的核心功能。

🎯 一、结果集映射 ​

1.1 ResultSetHandler ​

ResultSetHandler接口:

java
public interface ResultSetHandler {
    <E> List<E> handleResultSets(Statement stmt) throws SQLException;
    <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
}

1.2 DefaultResultSetHandler ​

DefaultResultSetHandler.handleResultSets:

java
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results")
            .object(mappedStatement.getId());
    
    final List<Object> multipleResults = new ArrayList<>();
    
    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);
        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);
}

🎯 二、对象创建 ​

2.1 对象实例化 ​

createResultObject:

java
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)) {
        return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (!constructorMappings.isEmpty()) {
        return createParameterizedResultObject(rsw, resultType, 
                constructorArgTypes, constructorArgs, constructorMappings, 
                columnPrefix);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
        return objectFactory.create(resultType);
    } else {
        throw new ExecutorException("Do not know how to create an instance of " + 
                resultType);
    }
}

2.2 属性填充 ​

applyPropertyMappings:

java
private void applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, 
        MetaObject metaObject, String columnPrefix) throws SQLException {
    final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, 
            columnPrefix);
    final List<ResultMapping> propertyMappings = 
            resultMap.getPropertyResultMappings();
    for (ResultMapping propertyMapping : propertyMappings) {
        final String column = prependPrefix(propertyMapping.getColumn(), 
                columnPrefix);
        if (propertyMapping.getNestedQueryId() != null) {
            value = getNestedQueryMappingValue(rsw, metaObject, 
                    propertyMapping, columnPrefix);
        } else if (propertyMapping.getResultSet() != null) {
            addPendingChildRelation(metaObject, propertyMapping);
        } else {
            final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
            final String property = propertyMapping.getProperty();
            if (typeHandler == null || property == null) {
                continue;
            }
            value = typeHandler.getResult(rsw.getResultSet(), column);
            if (value != null) {
                metaObject.setValue(property, value);
            }
        }
    }
}

🎯 三、延迟加载 ​

3.1 延迟加载实现 ​

ProxyFactory:

java
public interface ProxyFactory {
    Object createProxy(Object target, ResultLoaderMap lazyLoader, 
            Configuration configuration, ObjectFactory objectFactory, 
            List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
}

📖 学习资源 ​

视频教程 ​

书籍推荐 ​

  • 《MyBatis技术内幕》 - 徐郡明

网站资源 ​

✅ 学习检查清单 ​

  • [ ] 已理解结果集映射
  • [ ] 已理解对象创建
  • [ ] 已理解类型处理
  • [ ] 已理解延迟加载
  • [ ] 已总结核心知识点

上一章节:MyBatis SQL映射
下一章节:MyBatis缓存机制
返回目录:Mybatis和Tomcat源码深度解析