文章目录

  • 概要
  • 参数映射
  • 自定义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)--映射器相关推荐

  1. SQL Server性能调优之执行计划深度剖析 第二节 执行计划第一次实践

    SQL Server性能调优之执行计划深度剖析 第二节 执行计划第一次实践 前言:自从上一篇文章发出之后,收到了很朋友的关注.很多朋友要求多多实践,而不是纯粹的理论.确实,从打算出这个系列开始,我就本 ...

  2. 面试经常问的:mybatis的执行流程(比较简洁)

    mybatis的执行流程 在网找了好多,说的都很详细,但是太多不太简洁, 看以下代码就懂了: 实际流程大概就是注释的那几句话,面试的时候就这么说就行 1.获取mybatis配置文件并读取配置 2.获取 ...

  3. MyBatis 的执行流程,写得太好了!

    来源 | blog.csdn.net/zwx900102/article/details/108455514 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清 ...

  4. MyBatis 的执行流程,学废了!

    作者:双子孤狼 来源:blog.csdn.net/zwx900102/article/details/108455514 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不 ...

  5. MyBatis 的执行流程,面试的时候用得上

    前言 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清楚了,那么既然进来了,通读本文你将收获如下: 1.Mapper接口和映射文件是如何进行绑定的 2.MyB ...

  6. Mybatis基于XML配置SQL映射器(二)

    Mybatis之XML注解 之前已经讲到通过 mybatis-generator 生成mapper映射接口和相关的映射配置文件: 下面我们将详细的讲解具体内容 首先我们新建映射接口文档  sysUse ...

  7. [MyBatis日记](3)映射器配置文件与映射器接口

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50659993 前一篇文章([MyBatis日 ...

  8. mybatis的执行流程

    https://blog.csdn.net/u010890358/article/details/80665753 https://blog.csdn.net/u014297148/article/d ...

  9. Mybatis基于XML配置SQL映射器(一)

    Durid和Mybatis开发环境搭建 SpringBoot搭建基于Spring+SpringMvc+Mybatis的REST服务(http://www.cnblogs.com/nbfujx/p/76 ...

  10. 深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)

    原文地址:http://www.cnblogs.com/dongying/p/4142476.html 最近太忙了,一直没时间继续更新博客,今天忙里偷闲继续我的Mybatis学习之旅.在前九篇中,介绍 ...

最新文章

  1. 项目中非常有用并且常见的ES6语法
  2. wifi管理系统_KJ725(A)精确人员定位管理系统实现对井下人员和车辆的精确定位
  3. LEMP+memcached
  4. tensorflow 学习:用CNN进行图像分类
  5. 白话经典算法系列之六 快速排序 快速搞定
  6. 人工智能火爆,入门却太难了!
  7. PHP九宫格翻牌抽奖,PHP 九宫格抽奖代码
  8. 软件精选中的Windows软件安装目录,含软件包和安装教程
  9. 反激式开关电源电路测试记录(二)
  10. 【期末划重点】高数下期末考复习
  11. kettle同步数据 (SAP hana到 Mysql)
  12. 20172304 蓝墨云实验哈夫曼树
  13. 证券交易所的运作系统
  14. dlna 服务器 性能,dlna 使用体验,供大家参考,欢迎交流
  15. vue3中 v-md-editor 编辑器的基本使用分享
  16. Hark的数据结构与算法练习之圈排序
  17. windows 10 时间同步,时间显示不准自动校准。
  18. Node.js—Express、Express 路由 、Express 中间件、使用 Express 写接口
  19. 在计算机英语中 update是什么意思,电脑出现windows update是什么意思?
  20. JS 沙箱隔离简单实现

热门文章

  1. HTML5表白小程序
  2. MYSQL函数group_concat的使用
  3. android killer 反编译工具,androidkiller反编译软件使用与踩坑并解决的过程
  4. java省略号_在Java中使用省略号(…)
  5. 软件设计(中线提取)
  6. Mycat分库分表优缺点分析
  7. 产品需求文档(PRD)
  8. 工作中常见的两种谬误
  9. 数控编程也是c语言吗,学数控编程需要使用个人电脑吗
  10. 马云开酒吧了,酒吧叫“平头哥”,真猛~