DefaultResultSetHandler#handleResultSets 处理结果集
@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是对ResultSet元数据的封装
ResultSetWrapper rsw = getFirstResultSet(stmt);
//获取返回类型-resultType会被转换为Inline的ResultMap(id变为namespace+“Inline” see MapperBuilderAssistant#getStatementResultMaps)
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
//如果结果集不为空,resultMapCount<1抛出异常
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);
}
//处理当前结果集
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) {
//结果处理器为空resultHandler从构造Executor传入
//构造默认的结果处理器,使用objectFactory创建结果集
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
//处理当前ResultMap中每一行
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());
}
}
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
//如果有嵌套的(子句中包含select属性)
if (resultMap.hasNestedResultMaps()) {
//确保字句中没有分页
ensureNoRowBounds();
//确保子句中没有ResultHandler
checkResultHandler();
//处理嵌套的ResultMap
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
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);
//context中结果条数小于rowBounds的limit获取结果集下一个
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
//首先循环处理嵌套鉴别器,将解析后的最后一个resultMap作为当前resultMap,无鉴别器则返回当前resultMap
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
//获取当前行的值
Object rowValue = getRowValue(rsw, discriminatedResultMap);
//如过parentMapping不为空,将rowvalue设置给parent,否则回调自己的ResultHandler
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
}
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
//ResultLoaderMap存储了LoadPair的hashMap,对应一个对象,每一个LoadPair则对应
//对象的每一个属性和其延迟加载器 ResultLoader,ResultLoader封装了executor,parameterObject,objectFactory,cacheKey等必要的一切属性用来再次执行sql(包括当前线程和其他线程)
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//初始化返回对象,如过有嵌套查询则创建lazyLoader的代理对象,并返回
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
// 给rowvalue设置值
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;
}
分享到:
相关推荐
这里我们将深入探讨MBG的核心功能、工作原理以及如何使用mybatis-generator-core-1.3.2.jar这个版本来自动化生成代码。 首先,MyBatis Generator基于数据库表结构,通过配置文件指定数据库连接信息、表名以及需要...
在这个场景中,“逆向工程mybatis-generator-1.3.2”指的是对MyBatis Generator 1.3.2版本的源代码或执行流程进行逆向分析。MyBatis Generator(MBG)是一个强大的工具,能够自动生成MyBatis接口和映射器XML文件,...
总的来说,`mybatis-3-master` 源码分析可以帮助我们理解 MyBatis 内部的工作原理,提高我们对 SQL 执行流程、对象映射机制的理解,从而更好地优化数据库操作,提升系统性能。同时,通过阅读源码,开发者还能学习到...
8. StatementHandler:处理PreparedStatement对象,设置SQL参数和获取结果集。 9. MapperRegistry:注册Mapper接口和对应的MappedStatement,使得我们可以通过Mapper接口调用SQL。 在MyBatis源码中,你可以看到...
在本压缩包“mybatis-3-mybatis-3.5.4-src-read.zip”中,包含了作者对MyBatis 3.5.4版本源码的阅读理解,特别进行了关键部分的注解和流程解析,对于学习和深入理解MyBatis的工作原理非常有帮助。 1. **MyBatis架构...
总的来说,Mybatis Generator是Mybatis框架下的一个重要辅助工具,它极大地简化了开发流程,提高了开发效率,尤其是在处理大量表和字段的项目中,其价值尤为显著。对于任何使用Mybatis的团队来说,掌握并合理利用...
3. **StatementHandler**:处理SQL语句,包括预编译、设置参数、获取结果集等。它通过PreparedStatement和ResultSet与数据库进行交互。 4. **ParameterHandler**:处理输入参数,将Java对象转换为数据库可识别的...
4. **结果集处理**: 自动将查询结果映射成Java对象,这样就不需要手动遍历结果集并将每一列的值转换成Java对象了。 #### 五、环境搭建与配置 1. **下载MyBatis**: - 从GitHub ...
2. **工作原理** - 数据库连接:MyBatis-Auto-Generator-Core首先需要建立到数据库的连接,通过JDBC获取数据库元数据,包括表名、列名、数据类型等信息。 - 模板引擎:然后,它使用模板引擎(如FreeMarker或...
MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 在...
2. **结果映射**:MyBatis 提供了自动化的结果映射功能,可以根据数据库查询结果自动将数据行映射到 Java 对象上,同时也支持自定义映射,以处理复杂的数据库结果集。 3. **缓存机制**:为了提高性能,MyBatis 实现...
MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 在...
MyBatis Generator 的工作原理是通过读取数据库元数据,根据预设的模板生成对应的 Java 源代码。它支持多种数据库,包括 MySQL、Oracle、SQL Server 等。在使用 MBG 时,我们需要创建一个 XML 配置文件,其中定义了...
5. 结果处理:`ResultSetHandler`接口用于处理SQL查询返回的结果集,它可以将数据映射到Java对象或集合。MyBatis支持多种映射策略,包括一对一、一对多、多对多等关系的映射。 6. 缓存:MyBatis内置了两级缓存,一...
通过深入研究"Mybatis-3"的源码,我们可以理解其内部的执行流程,例如Executor的执行策略、StatementHandler的预编译和执行过程、ParameterHandler参数绑定的逻辑,以及ResultSetHandler结果集处理的细节。...
12. **MyBatis 执行流程**:了解 MyBatis 如何解析 XML 或注解,生成 PreparedStatement,执行 SQL,处理结果集,以及事务提交或回滚的过程。 13. **实战项目**:通过一个完整的案例,实践 MyBatis 的集成,包括...
Mybatis是一个轻量级的ORM(Object-Relational Mapping)框架,它避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis通过XML或注解方式配置和映射原生信息,将接口和Java的POJOs(Plain Old Java ...
MyBatis 是一款著名的Java持久层框架,它简化了数据库操作与Java对象之间的映射,提供了灵活的SQL构建和执行机制。在MyBatis-3.2.3这个版本中,我们可以深入研究其源码,了解其内部工作原理,这对于Java开发者尤其是...
通过上述分析,我们可以清晰地了解到Mybatis中SQL解析的整体流程:从创建SqlSessionFactory开始,到打开SqlSession,再到获取Mapper代理对象,最后执行SQL语句并获取结果。这一过程不仅展示了Mybatis强大的SQL解析...
5. **处理结果集**:遍历ResultSet并处理数据。 6. **释放资源**:确保所有使用的资源被正确关闭,避免内存泄漏等问题。 #### 七、MyBatis优势 1. **简化数据库操作**:通过配置文件或注解,简化了SQL语句的编写、...