MyBatis 源码分析——映射结果
MyBatis最后一步一定是处理相关的结果——把数据映射成对应的模型对象。事实上在笔者看来如果读者们了解了mybatis如何去执行数据库,又是如何处理数据结果。那么就了解了mybatis的主要路线。因为不管是什么样子的ORM最终都是要执行和处理结果的。而mybatis的亮点笔者也讲了——管理sql语句。所以相对而言,处理结果就显得十分的次要。但是笔者还是希望能在这里停留一下,研究他是如何处理结果。
mybatis处理结果的代码都在DefaultResultSetHandler类里面。很抱歉的是笔者去掉了程序是如何执行到DefaultResultSetHandler类的。这里面还是希望读者们自行的去跟踪一下。DefaultResultSetHandler类的handleResultSets方法便是笔者切入的代码。事实上当代码执行到handleResultSets方法的时候,已经执行了数据库。这在PreparedStatementHandler类里面就体现出来了。如下
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
用过mybatis的人都知道resultMap节点的作用。select节点的resultMap属性就是用来指点使用哪一个resultMap节点。而返回的结果也是用这一个节点来设置的。如下
<select id="SelectProducts" resultMap="result" >
select * from Products
where #{0} > ProductID and ProductName like #{1}
</select>
<resultMap type="com.aomi.vo.Product" id="result" autoMapping="true">
</resultMap>
所以我可以设想一下。当我们拿到了数据的时候,希望数据变成我们指定的对象模型。那么我们就必须知道是什么类型。一般来讲只要知道了什么类型就可以完成基本的映射条件。那么还会有可能出现一种希望自己去设计映射的字段和实例化对象。所以mybatis在这一方面也算是让笔者很喜欢。细详你可以查看一下官方的网站——XML映射文件。
在映射的过程中,往往我们都需要知道表的字段。所以在DefaultResultSetHandler类的handleResultSets方法里面一开始就获得了关于表的信息。表的信息都存放在ResultSetWrapper类里面。后面便就是根据这些信息来处理每一行的数据。我们还是看一下源码吧。
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); 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);
}
笔者标出切入需要的俩个代码段。一个就是获得表信息的,另一个就是用于处理每一行数据的。事实上面的multipleResults变量就能说明一个问题——可能实现多个select句语的执行。所以相对的reusltMap也变成了集合类型。在XML上面就是用逗号隔开的。笔者没有做过类似这种方式的代码。笔者也是从源码中看来的。他在MapperBuilderAssistant类的getStatementResultMaps方法里面。如下。
String[] resultMapNames = resultMap.split(",");
具体情况读者们可以自己去实验一下。
在笔者看来想要理解这一部分的关键点还在是getRowValue方法这边。这里面就是我们所说的处理结果。根据reusltMap节点的信息判断出是要自己根据类型生成对象。还是要通过reusltMap节点配置信息来生成对象。然后直行获值和设值。如下。
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
if (resultObject != null && !hasTypeHandlerForResultObject(rsw, 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;
}
1.createResultObject方法:根据类型和配置信息生成对象。
2.applyAutomaticMappings方法:判断是否是autoMapping="true",如果是就是自动映射赋值。
3.applyPropertyMappings方法:根据配置信息赋值。
接下来,就是各位读者们根据自己的需要进行进一步的研究了。如果想知道是如何生成对象就是去看createResultObject方法。赋值的话就去看applyAutomaticMappings方法和applyPropertyMappings方法。
MyBatis 源码分析——映射结果的更多相关文章
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- MyBatis 源码分析 - 插件机制
1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...
- MyBatis 源码分析 - 缓存原理
1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...
- MyBatis 源码分析 - 内置数据源
1.简介 本篇文章将向大家介绍 MyBatis 内置数据源的实现逻辑.搞懂这些数据源的实现,可使大家对数据源有更深入的认识.同时在配置这些数据源时,也会更清楚每种属性的意义和用途.因此,如果大家想知其 ...
- MyBatis 源码分析 - 配置文件解析过程
* 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...
- MyBatis 源码分析系列文章导读
1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...
- 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
随机推荐
- node.js 的事件机制
昨天到今天, 又看了一边node 的事件模块, 觉得很神奇~ 分享一下 - -> 首先, 补充下对node 的理解: nodeJs 是一个单进程单线程应用程序, 但是通过事件和回调支持并发 ...
- CSS3知识点整理(三)----变形与动画
一.CSS3中的变形 1)旋转 rotate() rotate()函数通过指定的角度参数使元素相对原点进行旋转. 它主要在二维空间内进行操作,设置一个角度值,用来指定旋转的幅度. 如果这个值为正值,元 ...
- GCD 多线程 ---的记录 iOS
先写一个GCD static UserInfoVoModel *userInfoShare = nil; +(instancetype)shareUserInfoVoModel { static di ...
- 网站SEO,HTTP请求的关键数字----6
客户端浏览器向服务器请求一个网页素材. 那么网页素材是通过什么方式,什么顺序被下载下来的呢. 我今天做了个简单的测试. 首先,准备测试文件 写一个网页,网页中引用若干的资源文件. 同一文件的不同的参数 ...
- python 模块加载错误总结
在运行yum时提示如下错误 There was a problem importing one of the Python modules required to run yum. The error ...
- sping整合hibernate之二:dao层开发
在上一篇日志中将hibernate的会话工厂sessionFactory注入到了spring的容器中,但这样还不够,因为hibernate的增删改查是要使用事务机制的, 所以还要在spring中配置 ...
- NFS安装及配置
NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系统能够彼此分享个 ...
- 杭电OJ2005——第几天
/*第几天?Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- angularjs+ionic注册页面表单验证(手机号、确认密码、60s后重发验证码)
在已建立tabs和路由的注册页面html: 功能: 进行了手机号.密码格式验证,两次密码输入是否相同的判断,都正确且复选框勾选后才可点击注册,进入tabs.mypage页面. 未进行验证码真正发送.获 ...
- DAX/PowerBI系列 - 父子层级(Parent-Child Hierarchy)
DAX/PowerBI系列 - 父子层级(Parent-Child Hierarchy)参考文章见最后 难度: ◆◆◇◇◇(2星) 应用场景: 其实很多时候对数据汇总都会有层级关系的问题,不过说的不是 ...