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源码深度解析