mybatis 之 SimpleStatementHandler 的 query方法怎么得到映射对象的list集合的

本文主要是介绍mybatis 之 SimpleStatementHandler 的 query方法怎么得到映射对象的list集合的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先,入口类 SimpleStatementHandler

 

@Overridepublic <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {String sql = boundSql.getSql();statement.execute(sql);return resultSetHandler.<E>handleResultSets(statement);}

进入mybatis默认的 DefaultResultSetHandler类 , 

handleResultSets方法 处理结果集的映射:
  @Overridepublic 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);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++;}

其他的不管,重点看 方法  handleResultSet(rsw, resultMap, multipleResults, null);

是怎么把 一个个ResultMap类型的映射对象 转变成 java的具体对象。

具体的java对象是保存在 multipleResults中的,如 debug截图所示:

 

解析参数:

ResultSetWrapper rsw : 该参数中 包含了 配置在mapper.xml中的某个映射对象(resultMap或resultType)的 几乎所有信息。
class ResultSetWrapper {private final ResultSet resultSet;private final TypeHandlerRegistry typeHandlerRegistry;private final List<String> columnNames = new ArrayList<String>();--列名private final List<String> classNames = new ArrayList<String>();--类路径名private final List<JdbcType> jdbcTypes = new ArrayList<JdbcType>();--JdbcType类型列表private final Map<String, Map<Class<?>, TypeHandler<?>>> typeHandlerMap = new HashMap<String, Map<Class<?>, TypeHandler<?>>>();

debug得到的 ResultSetWrapper rsw 对象的内容如下:

 

开始重点分析:

类DefaultResultSetHandler的方法handleRowValues中的方法handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);

不考虑嵌套(只考虑单个result模式下,怎么把sql得到的resultType或resultMap对象转化成具体的javaBean对象的,包括javaBean对象的字段,各个方法)。

 

获取单row的值:

DefaultResultSetHandler 的 getRowValue 方法

DefaultResultSetHandler 的 createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) 方法

因为mybatis dao层里面的都是接口,所以此时拿到

final Class<?> resultType = resultMap.getType();

里面返回的javaBean对象,

使用ObjectFactory工厂 以及resultType 里的类路径 创建类的实例。

DefaultObjectFactory

@Override
public <T> T create(Class<T> type) {return create(type, null, null);
}

 

此时创建的resultObject对象是一个 参数皆为空的对象,还需要赋值。

 

resultObject对象赋值的话,实现的是 接口

TypeHandler的  getResult(ResultSet rs, String columnName) 或 getResult(ResultSet rs, int columnIndex) 方法,

通过 列名或者列索引 查询得到结果集rs中 对应字段的值,赋值到resultObject对象的相应字段。

 

最后 回到类DefaultResultSetHandler 的

handleRowValuesForSimpleResultMap()方法的 
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());

保存映射得到的结果对象。

 

debug下去,把映射的结果集传回来:

closeResultSet(rsw.getResultSet());

关闭该行记录的rsw, 

 

最终 

return collapseSingleResultList(multipleResults);

类PreparedStatementHandler 的  return resultSetHandler.<E> handleResultSets(ps);

类SimpleExecutor的

return handler.<E>query(stmt, resultHandler);
closeStatement(stmt); 关闭 Statement

 

回到最外层的实现类 DefaultSqlSession 

的 selectOne(String statement, Object parameter)

 

返回对象。 结束:

 

回过头来 看一下最重要的几行代码:

类DefaultResultSetHandler 中的:

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);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());}}
第一步:skipRows(rsw.getResultSet(), rowBounds); 根据rowBounds中的offset值 定位到指定的记录行

第二步: 

while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { 校验是否还有需要映射的记录

 

第三步:

ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);

确定映射使用的 resultMap 对象。

最复杂的一步:

Object rowValue = getRowValue(rsw, discriminatedResultMap); 对resultMap中的一行记录进行映射。(分两步:首先创建resultMap对应的 javaBean对象,然后给该javaBean对象的每个字段一一赋值)。

 

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;}
Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null); 创建对象

 

foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; 给创建的对象的每一行 赋值。

这篇关于mybatis 之 SimpleStatementHandler 的 query方法怎么得到映射对象的list集合的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/942168

相关文章

统计学方法的比较与评估

分析不同统计学方法的优缺点以及它们在特定情境下的适用性是一个复杂而有趣的课题。下面我将简要讨论一些常见的统计学方法,并比较它们的特点: 1. **参数统计与非参数统计:**    - 参数统计:假设总体分布的形态,并基于样本数据对总体参数进行估计和假设检验。优点是通常效率高,但缺点是对总体分布的假设可能不成立。    - 非参数统计:不对总体分布形态做出假设,通常基于样本数据的秩或排名进行推断。

已解决java.lang.AbstractMethodError: 抽象方法错误的正确解决方法,亲测有效!!!

已解决java.lang.AbstractMethodError: 抽象方法错误的正确解决方法,亲测有效!!! 目录 问题分析 报错原因 解决思路 解决方法 更新和重新编译依赖 确认类和接口的版本一致性 类加载器配置检查 总结 问题分析 java.lang.AbstractMethodError通常在尝试调用一个抽象方法的实现时抛出,但是该实现在运行时并未被找到。

重构四要素:目的、对象、时机和方法

目录 1.引言 2.重构的目的:为什么重构(why) 3.重构的对象:到底重构什么(what) 4.重构的时机:什么时候重构(when) 5.重构的方法:应该如何重构(how) 6.思考题 1.引言         一些软件工程师对为什么要重构(why)、到底重构什么(what)、什么时候重构(when)应该如何重构(how)等问题的理解不深,对重构没有系统行认识、在面对质量不

drawable转file方法

drawable转file方法: /** * drawable转为file * @param mContext * @param drawableId drawable的ID * @param fileName 转换后的文件名 * @return */ public File drawableToFile(Contex

APP字体大小,不随系统的字体大小变化而变化的方法

从android4.0起系统设置的”显示“提供设置字体大小的选项。这个设置直接会影响到所有sp为单位的字体适配,所以很多app在设置了系统字体后瞬间变得面目全非。下面是解决方案 [java]  view plain copy print ? Resources res = super.getResources();   Configuration config=new Co

华为手机恢复出厂设置后怎么还原数据?该如何预防数据丢失?

华为手机恢复出厂设置是将手机恢复到出厂时的初始状态,同时会删除所有用户数据和个人设置。如果不做任何预防措施,在恢复出厂设置后,您将丢失手机上的所有数据。那华为手机恢复出厂设置后怎么还原数据呢?以下是关于如何在华为手机还原数据的方法以及预防数据丢失的建议。 如何还原数据? 通常来说,还原数据的方法有很多,使用手机操作就可以达到目的,但是恢复出厂设置后的手机数据还原令很多人手足无措。原

Spring new对象时注解失效

一、背景 今天在写代码时,有一个类: public class StoreInfoTool{ @Resource QAAssistantTool qaAssistantTool; public void run(){         qaAssistantTool.search(xx); } } 执行时报错,提示qaAssistantTool为空。 然后就发现很奇怪,qaA

【LeetCode】203. Remove Linked List Elements

//LeetCode 203. 删除链表中的元素#include "stdafx.h"#include <iostream>using namespace std;typedef int ElemType;struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}};class Solut

uri.getQueryParameters(name)返回一个列表(List)

uri.getQueryParameters(name)返回一个列表(List)而不是单个值的原因在于URI(统一资源标识符)中查询参数(query parameters)的设计允许同一个名称(name)对应多个值。这意味着一个查询参数可以重复出现多次,并且每次都可能有不同的值。 背景 在Web开发和很多网络协议中,URI用于指定如何访问一个资源,其中查询字符串(Query String)是U

MFC/QT利用COM组件接口从字体名称、粗体、斜体获取到字体文件路径的方法

MFC/QT利用COM组件接口从字体名称、粗体、斜体获取到字体文件路径的方法 这个是目前唯一能准确从字体名称+加粗+斜体三个属性定位到ttf/ttc字体路径的方法,其他的方式是没有办法区分后两个属性而且会出现不准确的问题 之前无意间在MSDN找到的资料: IDWriteLocalFontFileLoader::GetFilePathFromKey (dwrite.h) - Win32 app