MyBatis源码(五)之动态Sql解析运行阶段参数处理

上篇博文分析到Mapper文件的读取,以及启动过程动态Sql的解析部分 MyBatis源码(四)之mapper文件解析和动态Sql解析启动阶段

本博文继续动态Sql的解析,在运行时的解析。前文也提过,在动态Sql中,sql的最终生成是依靠传入的参数来决定的。所以在继续分析之前先来分析下是mybatis是怎么接收参数的。

dao参数上可能有@Param注解,参数中可能有集合Collection,如何跟之前配置文件中的javaType,parameterType对应起来等等。

dao的代理类MapperProxy的invoke方法,invoke能获取到拦截的方法的元数据信息和入参
去掉Object的方法之后拦截所有的dao方法。

跟进看下拦截Dao的方法是具体做什么的

MapperMethod

MapperMethod的一个成员MethodSignature,也是MapperMethod的内部类(mybatis的一个特点是比较喜欢使用内部类)重点看下参数部分:

MethodSignature

MapperMethod封装了被拦截方法的信息,包括:

返回类型
是否返回多行
是否有ResultHandler接口类型的参数
被拦截方法的参数信息

如下dao方法对应上面的截图:

List<HrdDemandMatching> batchQueryBySellerIds(@Param("demandId")Long demandId,
                @Param("sellerMemberIdLs") List<String> sellerMemberIdLs);

如果方法在有一个参数 就是 params就在添加一个key和value对 2= 2
key表示参数的下标2
value表示参数的名字(被注解@param标示) 没有的话value也是下标 即这里的 2 = 2
MethodSignature的这个params的TreeMap只是参数下标和名字而已,此时并没有放入参数,下面将参数填入参数值。
MapperMethod执行
MethodSignature将参数填入参数值

代理拦截方法之后委托给mapperMethod.execute还行,
covertArgsToSqlCommandParam这个方法将参数值和参数名对应起来,返回的是Object。

1)没有参数返回null
2)1个参数返回args[0]
3)多于1个返回Map,key:有@param注解的名字,没有param取下标

第三条除了将参数名和值放入map 同时又额外添加了一份参数的信息
如这里的param1和param2第一个下标参数的值,第二个下标参数的值,本博文后边还会用到这个!

其实MapperMethod.execute方法主要的是组织入参,选择执行SqlSession的那个方法 根据标签 select insert update delete和方法的返回值类型。

现在还没有完,还要方法参数转换成配置文件中对应的值和类型才完工。参数映射部分才刚刚开始!!
我们继续跟代码,这一步就是根据具体的 select insert等标签或者返回值决定调用那个具体的sqlsessionTemplate的方法(也是SqlSession的方法)
这里写图片描述
这里写图片描述
还记得吗 这里的SqlSession值的是谁?SqlSessionTemplate
SqlSessionTemplate的成员sqlSessionProxy – SqlSessionInterceptor,
SqlSessionTemplate也实现了SqlSession,所有的SqlSession方法都是用这个sqlSessionProxy 完成的,所有sqlSessionTemplate的方法都会被SqlSessionInterceptor拦截住,进而获取真正的SqlSession的实现,通过DefaultSqlSessionFactory.openSession创建DefaultSqlSession(SimpletExecutor,Transaction也都创建并且塞入到DefaultSqSession了)!!!这是如果忘记了可以看下之前的博文。
SqlSessionTemplate的成员SqlsessionInterceptor创建DefaultSqlSession
这里不再复述,只是贴下代码如读者回忆一下。

接下来进入到DefaultSqlSession的方法

DefaultSqlSession.selectList

DefaultSqlSession.selectList()方法SimpleExecutor.query方法的参数
wrapCollection(parameter)这个方法也值得看下:
dao方法超过两个会被当成map,两个以内是原生的对象类型,
该方法处理集合类型具体规则如下:

1、集合类型非map类型的直接map.put(“collection”,object);
2、集合类型是List的map.put("list",object)
3、数组map.put("array",object)

可见,只要超过两个参数的都会转成map collection和array的也不例外,都是map。

这里写图片描述

本篇将的主要是dao的参数是如何传入和处理的,贴图较多是为了让大家回顾下之前的流程不要看过忘了:

两个以内的参数都是不做转换,如果是collection的或者array会转换成map
两个参数或者以上,直接转成map。

这里请求流程只是到了SimpleExecutor.execute
将dao的参数处理完毕了,但是参数是怎么跟sql中的入参对接上,以及sql是如何根据参数生成最终执行的sql还没有讨论。

猜你喜欢

转载自blog.csdn.net/mayongzhan_csdn/article/details/78606911