mybatis内置select

前面已经看过了内置的增删改,这次来看下select的使用,如图1:
图1:

追着方法下去,最后能看到其实调用的是,selectList方法,如图2:
图2:

从图2能看到,首先从Configuration中获取到了statement,那看下在初始化的时候是怎么加载MappedStatement的,先会解析select|insert|update|delete如图3:
图3:

如图4,会实例化一个XMLStatementBuilder,通过XMLStatementBuilder来生成MappedStatement
图4:

parseStatementNode会解析4个标签中的各种信息,如图5
图5:

最后会通过MapperBuilderAssistant,把MappedStatement放入到configuration的mappedStatements中去,如图6
图6:

在addMappedStatement方法中,通过MappedStatement.Builder构建MappedStatement,并放入到configuration中,如图7
图7:

那么在回过头来继续看select,在获得MappedStatement后,会通过执行器执行query,看下query做了什么事情,如图8:
图8

在初始化的Executor是会变成CachingExecutor,还有一个Executor作为代理,如果不指定的话默认是SimpleExecutor
那么,会从MappedStatement中获取BoundSql,如图9:
图9

BoundSql又是从SqlSource获取,那就先来看下SqlSource吧,初始化阶段,在解析select|insert|update|delete的时候,会生成一个SqlSource,如图10:
图10

LanguageDriver默认是XMLLanguageDriver,在Configuration实例化的时候已经加载好,这里就不展示了
那么来看下createSqlSource到底做了些什么,如图11:
图11

这里实例化了XMLScriptBuilder,如图12:
图12

这里就是所有的标签如<if>、<foreach>等,都会放入nodeHandlerMap中,然后通过parseScriptNode方法解析,如图13:
图13:

在这里会判断是否是动态sql还是静态sql,动态sql就是包含有${}和<if>,那么来看下parseDynamicTags这个方法,如图14:
图14

这里就是解析${}和<if>等标签,然后通过nodeHandlerMap获取对应的NodeHandler,通过handler.handleNode(child, contents)来解析<if>,<foreach>等,如解析<where>如图15,最后放到MixedSqlNode的List<SqlNode> contents中
图15

如果有${}就是动态sql,会实例化DynamicSqlSource,不然就是实例化RawSqlSource
那么来看下RawSqlSource,DynamicSqlSource的话到后面才会解析,如图16:
图16

看下这里的getSql做了什么事情,如图17:
图17

实例化了DynamicContext,因为是静态sql,所以不会有${}占位符,所以是StaticTextSqlNode,MixedSqlNode会去循环处理,如图18,19:
图18

图19

DynamicContext中就已经有了一个普通的sql,就会去替换#{}的占位符,如图20:
图20

通过SqlSourceBuilder来解析#{},并替换成?,如图21:
图21

那在回过头来看下SqlSource获取BoundSql,因为前面看到是静态sql,所以是RawSqlSource,但是在RawSqlSource有个sqlSource是StaticSqlSource,那么直接看StaticSqlSource中的getBoundSql方法,如图22:
图22

是直接实例化了一个BoundSql,把需要的一些信息都放在了BoundSql中
接着调用BaseExecutor中的query方法,如图23:
图23

重点看下queryFromDatabase这个方法,如图24:
图24

这里还封装了一个doQuery方法,因为在初始化Executor的时候是CachingExecutor,在CachingExecutor又有一个代理,默认是SimpleExecutor,所以直接到SimpleExecutor查看doQuery方法,如图25:
图25

这里是会生成一个StatementHandler,通过StatementHandler会去实例化一个Statement,先看下configuration.newStatementHandler这个方法,如图26:
图26

这里实例化了一个RoutingStatementHandler,看下RoutingStatementHandler的构造函数,如图27:
图27

在这里又出现一个代理,在初始化的时候,会判断是哪一种Statement,默认使用的是PREPARED,如图28:
图28

那继续看下图23中的prepareStatement方法,如图29:
图29

获取连接,并设置时间和设置参数,先看下handler.prepare这个方法,如图30:
图30

主要做了三件事,设置prepareStatement,设置查询超时时间,和fetchSize(mysql貌似不支持),主要看下设置prepareStatement,如图31:
图31

最后就是对应的?问号设置对应的值了,如图32:
图32

然后通过刚生成的PreparedStatement去查询,如图33:
图33

在来看下动态sql是怎么解析的,和静态的唯一区别就是在getBoundSql,如图34:
图34

在前面会解析到<if>等标签和${},如果是碰到${},那么就是TextSqlNode,先来看下DynamicContext的构造函数,如图35:
图35

在来看下TextSqlNode是怎么解析的,如图36:
图36

能看到BindingTokenParser,那么看下BindingTokenParser具体是怎么解析${}占位符的,如图37:
图37

从DynamicContext中获取刚刚放入的参数,通过Ognl来解析并赋值,解析的过程和静态sql是一样的,都是通过MixedSqlNode来循环解析,
解析完这些动态数据后,会把#{}替换成?,流程和静态sql是一样的。
 

接下来就要看下返回的数据是怎么处理的了,因为默认用PreparedStatementHandler,直接继承了父类的构造函数,图38
图38
下面就是ResultSet后进行数据的转换了,如图39:
图39
那么以上就是mybatis内置select了。下次来看下getMapper是怎么样的。
如有不对请指出,共同提供,谢谢!!!

猜你喜欢

转载自www.cnblogs.com/shenqiaqia/p/10602635.html