深度剖析MyBatis 的执行流程(3)--映射器
文章目录
- 概要
- 参数映射
- 自定义typeHandler
- 结果集映射
- 自定义typeHandler结果集
- 工作流程图
- 总结
概要
映射器是MyBatis中最核心的组件之一,在MyBatis 3之前,只支持xml映射器,即:所有的SQL语句都必须在xml文件中配置。而从MyBatis 3开始,还支持接口映射器,这种映射器方式允许以Java代码的方式注解定义SQL语句,非常简洁。
我们就从这里开始讲起。。。。。。。
参数映射
现在我们来看一下上面在执行查询之前参数是如何进行设置的,我们先进入prepareStatement方法:
我们发现,最终是调用了StatementHandler中的parameterize进行参数设置,接下来这里为了节省篇幅,我们不会一步步点进去,直接进入设置参数的方法:
上面的BaseTypeHandler是一个抽象类,setNonNullParameter并没有实现,都是交给子类去实现,而每一个子类就是对应了数据库的一种类型。下图中就是默认的一个子类StringTypeHandler,里面没什么其他逻辑,就是设置参数。
可以看到String里面调用了jdbc中的setString方法,而如果是int也会调用setInt方法。看到这些子类如果大家之前阅读过我前面讲的MyBatis参数配置,应该就很明显可以知道,这些子类就是系统默认提供的一些typeHandler。而这些默认的typeHandler会默认被注册并和Java对象进行绑定:
正是因为MyBatis中默认提供了常用数据类型的映射,所以我们写Sql的时候才可以省略参数映射关系,可以直接采用下面的方式,系统可以根据我们参数的类型,自动选择合适的typeHander进行映射:
select user_id,user_name from lw_user where user_name=#{userName}
上面这条语句实际上和下面这条是等价的:
select user_id,user_name from lw_user where user_name=#{userName,jdbcType=VARCHAR}
或者说我们可以直接指定typeHandler:
select user_id,user_name from lw_user where user_name=#{userName,jdbcType=VARCHAR,typeHandler=org.apache.ibatis.type.IntegerTypeHandler}
这里因为我们配置了typeHandler,所以会优先以配置的typeHandler为主 不会再去读取默认的映射,如果类型不匹配就会直接报错了:
看到这里很多人应该就知道了,如果我们自己自定义一个typeHandler,然后就可以配置成我们自己的自定义类。所以接下来就让我们看看如何自定义一个typeHandler
自定义typeHandler
自定义typeHandler需要实现BaseTypeHandler接口,BaseTypeHandler有4个方法,包括结果集映射,为了节省篇幅,代码没有写上来:
package com.lonelyWolf.mybatis.typeHandler;import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class MyTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement preparedStatement, int index, String param, JdbcType jdbcType) throws SQLException {System.out.println("自定义typeHandler生效了");preparedStatement.setString(index,param);}
然后我们改写一下上面的查询语句:
select user_id,user_name from lw_user where user_name=#{userName,jdbcType=VARCHAR,typeHandler=com.lonelyWolf.mybatis.typeHandler.MyTypeHandler}
然后执行,可以看到,自定义的typeHandler生效了:
结果集映射
接下来让我们看看结果集的映射,回到上面执行sql流程的最后一个方法:
resultSetHandler.handleResultSets(ps)
结果集映射里面的逻辑相对来说还是挺复杂的,因为要考虑到非常多的情况,这里我们就不会去深究每一个细节,直接进入到正式解析结果集的代码,下面的5个代码片段就是一个简单的但是完整的解析流程:
从上面的代码片段我们也可以看到,实际上解析结果集还是很复杂的,就如我们上一篇介绍的复杂查询一样,一个查询可以不断嵌套其他查询,还有延迟加载等等一些复杂的特性 的处理,所以逻辑分支是有很多,但是不管怎么处理,最后的核心还是上面的一套流程,最终还是会调用typeHandler来获取查询到的结果。
是的,你没猜错,这个就是上面我们映射参数的typeHandler,因为typeHandler里面不只是一个设置参数方法,还有获取结果集方法(上面设置参数的时候省略了)。
自定义typeHandler结果集
所以说我们还是用上面那个MyTypeHandler 例子来重写一下取值方法(省略了设置参数方法):
package com.lonelyWolf.mybatis.typeHandler;import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class MyTypeHandler extends BaseTypeHandler<String> {/*** 设置参数*/@Overridepublic void setNonNullParameter(PreparedStatement preparedStatement, int index, String param, JdbcType jdbcType) throws SQLException {System.out.println("设置参数->自定义typeHandler生效了");preparedStatement.setString(index,param);}/*** 根据列名获取结果*/@Overridepublic String getNullableResult(ResultSet resultSet, String columnName) throws SQLException {System.out.println("根据columnName获取结果->自定义typeHandler生效了");return resultSet.getString(columnName);}/*** 根据列的下标来获取结果*/@Overridepublic String getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {System.out.println("根据columnIndex获取结果->自定义typeHandler生效了");return resultSet.getString(columnIndex);}/*** 处理存储过程的结果集*/@Overridepublic String getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {return callableStatement.getString(columnIndex);}
}
改写Mapper映射文件配置:
<resultMap id="MyUserResultMap" type="lwUser"><result column="user_id" property="userId" jdbcType="VARCHAR" typeHandler="com.lonelyWolf.mybatis.typeHandler.MyTypeHandler" /><result column="user_name" property="userName" jdbcType="VARCHAR" /></resultMap><select id="listUserByUserName" parameterType="String" resultMap="MyUserResultMap">select user_id,user_name from lw_user where user_name=#{userName,jdbcType=VARCHAR,typeHandler=com.lonelyWolf.mybatis.typeHandler.MyTypeHandler}</select>
执行之后输出如下:
因为我们属性上面只配置了一个属性,所以只输出了一次。
工作流程图
上面介绍了代码的流转,可能绕来绕去有点晕,所以我们来画一个主要的对象之间流程图来更加清晰的展示一下MyBatis主要工作流程:
从上面的工作流程图上我们可以看到,SqlSession下面还有4大对象,这4大对象也很重要,后面学习拦截器的时候就是针对这4大对象进行的拦截,关于这4大对象的具体详情,我们下一篇文章再展开分析。
总结
本文主要分析了MyBatis的SQL执行流程。在分析流程的过程中,我们也举例论证了如何自定义typeHandler来实现自定义的参数映射和结果集映射,不过MyBatis中提供的默认映射其实可以满足大部分的需求,如果我们对某些属性需要特殊处理,那么就可以采用自定义的typeHandle来实现,相信如果本文如果读懂了,以下几点大家应该至少会有一个清晰的认识:
1、Mapper接口和映射文件是如何进行绑定的
2、MyBatis中SQL语句的执行流程
3、自定义MyBatis中的参数设置处理器typeHandler
4、自定义MyBatis中结果集处理器typeHandler
当然,其中很多细节并没有提到,而看源码我们也并不需要追求每一行代码都能看懂,就比如我们一个稍微复杂一点的业务系统,即使我们是项目开发者如果某一个模块不是本人负责的,恐怕也很难搞清楚每一行代码的含义。所以对于MyBatis及其他框架的源码中也是一样,首先应该从大局入手,掌握整体流程和设计思想,然后如果对某些实现细节感兴趣,再深入进行了解。
深度剖析MyBatis 的执行流程(3)--映射器相关推荐
- SQL Server性能调优之执行计划深度剖析 第二节 执行计划第一次实践
SQL Server性能调优之执行计划深度剖析 第二节 执行计划第一次实践 前言:自从上一篇文章发出之后,收到了很朋友的关注.很多朋友要求多多实践,而不是纯粹的理论.确实,从打算出这个系列开始,我就本 ...
- 面试经常问的:mybatis的执行流程(比较简洁)
mybatis的执行流程 在网找了好多,说的都很详细,但是太多不太简洁, 看以下代码就懂了: 实际流程大概就是注释的那几句话,面试的时候就这么说就行 1.获取mybatis配置文件并读取配置 2.获取 ...
- MyBatis 的执行流程,写得太好了!
来源 | blog.csdn.net/zwx900102/article/details/108455514 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清 ...
- MyBatis 的执行流程,学废了!
作者:双子孤狼 来源:blog.csdn.net/zwx900102/article/details/108455514 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不 ...
- MyBatis 的执行流程,面试的时候用得上
前言 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清楚了,那么既然进来了,通读本文你将收获如下: 1.Mapper接口和映射文件是如何进行绑定的 2.MyB ...
- Mybatis基于XML配置SQL映射器(二)
Mybatis之XML注解 之前已经讲到通过 mybatis-generator 生成mapper映射接口和相关的映射配置文件: 下面我们将详细的讲解具体内容 首先我们新建映射接口文档 sysUse ...
- [MyBatis日记](3)映射器配置文件与映射器接口
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50659993 前一篇文章([MyBatis日 ...
- mybatis的执行流程
https://blog.csdn.net/u010890358/article/details/80665753 https://blog.csdn.net/u014297148/article/d ...
- Mybatis基于XML配置SQL映射器(一)
Durid和Mybatis开发环境搭建 SpringBoot搭建基于Spring+SpringMvc+Mybatis的REST服务(http://www.cnblogs.com/nbfujx/p/76 ...
- 深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
原文地址:http://www.cnblogs.com/dongying/p/4142476.html 最近太忙了,一直没时间继续更新博客,今天忙里偷闲继续我的Mybatis学习之旅.在前九篇中,介绍 ...
最新文章
- 项目中非常有用并且常见的ES6语法
- wifi管理系统_KJ725(A)精确人员定位管理系统实现对井下人员和车辆的精确定位
- LEMP+memcached
- tensorflow 学习:用CNN进行图像分类
- 白话经典算法系列之六 快速排序 快速搞定
- 人工智能火爆,入门却太难了!
- PHP九宫格翻牌抽奖,PHP 九宫格抽奖代码
- 软件精选中的Windows软件安装目录,含软件包和安装教程
- 反激式开关电源电路测试记录(二)
- 【期末划重点】高数下期末考复习
- kettle同步数据 (SAP hana到 Mysql)
- 20172304 蓝墨云实验哈夫曼树
- 证券交易所的运作系统
- dlna 服务器 性能,dlna 使用体验,供大家参考,欢迎交流
- vue3中 v-md-editor 编辑器的基本使用分享
- Hark的数据结构与算法练习之圈排序
- windows 10 时间同步,时间显示不准自动校准。
- Node.js—Express、Express 路由 、Express 中间件、使用 Express 写接口
- 在计算机英语中 update是什么意思,电脑出现windows update是什么意思?
- JS 沙箱隔离简单实现