mybatis核心源码(SqlSessionFactory初始化)
了解mybatis源码之前,必须知道mybatis工作的大体工作原理,后续读起来就不会那么吃力;
1 mybatis源码简要剖析(一定要看)
1.1 mybatis的核心对象(有点印象即可):
sqlnode(接口):用于存储sql的节点,比如if判断,或者直接获取的sql信息,
mixsqlNode:下面两个sqlnode
TextSqlnode:存储有$的sql信息
StaticSqlNode:存储没有$的sql信息
sqlsource:存储获取到的mixsqlnode;
rowsqlsource:存储没有$的sqlnode,且没有其他节点
dimynicSqlsource:存储有$的sqlnode,或者有子节点
configration:存储初始化的配置信息;
mapperstatement:存储sqlnode,参数等信息;
mapperstatements:存储mapperstatement等信息
1.2 mybatis从数据库获取数据的模式我会不会看不懂?
不要把mybatis看的多么高大上,其实他使用的就是jdbc;
1.3 mybatis写一些判断sql很高大上,是不是很难?
用过mybatis的都知道,mybatis有很多sql片段(sqlnode),比如if,for循环等一系列,其实这些的作用就是用于拼接说sql;然后使用jdbc里面用过的statement执行即可;
1.4 我的sql写在xml中,mybatis用这个sql的时候是不是很麻烦?
其实mybatis会把xml里写的sql,封装到map中,你根据id去取就行,然后进行执行即可
总结:
mybatis把xml里面的sqlnode加载到一个map中,然后根据你的参数进行sql拼接,然后使用jdbc去执行拼接后的sql,然后把返回结果给你
2 源码具体细节如下:
1.创建SqlSessionFactory
SqlSessionFactory.build
2.1初始化解析xml(把xml解析成document对象)
其中的过程可以理解为创建一个configration对象(后续用于存储sql相关的东西),把xml转换成document对象,用于后续解析sql以及配置
2.2构建DefaultSqlSessionFactory对象
build(parser.parse())
(1)把document对象解析成可以使用的configration对象
解析各种不同的标签,这里包括环境node和mapper的配置 node;环境node解析比较简单,使用dom4j的xml对象解析获取即可;解析完成,则把对应的node数据封装到configration里面以便于后续执行sql时候使用;
mapper的解析相对稍微复杂一点点;下面主要分析一下mapper的解析过程;
2.2.1 mapper解析
XMLConfigBuilder#mapperElement:
根据上面拿到的mappers里的路径获取mapper文件,对mapper进行解析;
获取到mapper资源后,同样获取到mapper的document对象,然后对document对象解析;
下面直接看parse方法;
主要看核心的select(insert,update,delete都的模式都是一样的);
直接看解析过程(方法太长,这里就不截图了):
org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
大致流程如下:获取sqlid,StatementType,返回类型,参数类型,等一系列配置信息;
然后创建sqlsourse;
使用下面方法把sql解析成sqlsource;
直接进入方法看解析过程:
这里主要是对sqlnode的封装,没有难度,但是也算是属于mybatis的精髓之一;
先解析出一个混合的sqlnode,然后把他封装到sqlsource;
1)如果当前sql任意的node包含$,则把当前sql当做动态sql处理
2)包含$的sqlnode,封装到dynamicsqlsource里面,其他的封装到Rawsqlsource里面;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QVjveRdr-1620886406525)(mybatis核心源码.assets/image-20210513112911238.png)]
2.2.2sqlnode解析
对sqlnode进行解析,替换其中的#{},替换为?字符(这里用的是ognl表达式替换的),封装成TextsqlNode,然后判断当前是不是带$的sqlnode,是则把isDynamic赋值为true,同时把sqlnode添加到当前的的sql节点中,如果不是,则创建StatisTextSqlNode,放入节点;
如果还有子节点,则也人为sql是动态sql;使用策略模式,获取对应的sqlnode解析器,然后对其进行封装,同上;
再把汇总好的sqlnode放入mixsqlnode中,然后再根据isDynamic,放入到对应的sqlsource;
2.2.3 把sql封装到mapperstatement
在这个过程中会把mapperstatement存储到configration的mappedStatements中,以用于后面的调用,存的key就是namespace+sqlid;后面可以使用这个key来获取调用sql
到此mybatis的SqlSessionFactory初始化结束;
初始解析流程大概总结为
获取mapper文件->获取mapper的sql片段->把sql片段分解成sqlnode(两张动态/静态)->sqlnode封装到mixsqlnode->把sqlnode封装到sqlsource(根绝isDynamic值)->把sqlsource和sql片段的基本数据封装到mapperstatement对象中->mapperstatement封装到mapperstatements中
lnode(两张动态/静态)->sqlnode封装到mixsqlnode->把sqlnode封装到sqlsource(根绝isDynamic值)->把sqlsource和sql片段的基本数据封装到mapperstatement对象中->mapperstatement封装到mapperstatements中
sqlsession和sql的执行在见一篇文章;
关注我,好的笔记与共享!