作者:江南入直 http:// cnblogs.com/scuury/p/10 371246.html
推荐阅读
1. SpringBoot 整合篇
2. 手写一套迷你版HTTP服务器
3. 记住:永远不要在MySQL中使用UTF-8
4. Springboot启动原理解析
近来想写一个mybatis的分页插件,但是在写插件之前肯定要了解一下mybatis具体的工作原理吧,于是边参考别人的博客,边看源码就开干了。
核心部件:
- SqlSession
- Executor
- StatementHandler
- ParameterHandler
- ResultSetHandler
- TypeHandler
- MappedStatement
- Configuration
在分析工作原理之前,首先看一下我的mybatis全局配置文件
<?
第一步:创建一个sqlSessionFactory
在了解如何创建sqlSessionFactory之前,先看一下mybatis是如何加载全局配置文件,解析xml文件生成Configuration的
public
private
在上面的第二段代码中有一句
mapperElement(root.evalNode("mappers"));
刚好我们的全局配置文件中有一个mapper的配置,由此可见,mapperElemet()方法是解析mapper映射文件的,具体代码如下
private
根据以上代码可以分析,在写mapper映射文件的地址时不仅可以写成resource,还可以写成url和mapperClass的形式,由于我们用的是resource,所以直接进入第一个判断,最后解析mapper映射文件的方法是
private
其中具体解析每一个sql语句节点的是
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
进入这个方法一层层深究,最后到这里可以知道MappedStatement是由builderAssistant(即MapperBuildAssistant)创建的。
public
最后进入方法addMappedStatement(),mappedStatement最后以id为键保存在了Configuration中的一个map变量mappedStatements中。
public
最后回到我们的创建sqlSessionFactory上,之前的一切都是为了生成一个sqlSessionFactory服务的
public
从上面的代码可以看出最后是通过以Configuration为参数build()方法生成DefautSqlSessionFactory。
第二步:创建sqlSession
public
private
//返回一个SqlSession,默认使用DefaultSqlSession
executor在这一步得到创建,具体的使用在下一步。
第三步:执行具体的sql请求
在我的代码里执行的是
User
具体到里面的方法就是
public
在这里通过statementId拿到了我们在第一步存在map里面的MappedStatement。在这里引用参考博客的一句话:
SqlSession根据Statement ID, 在mybatis配置对象Configuration中获取到对应的MappedStatement对象,然后调用mybatis执行器来执行具体的操作。
再继续看query()和queryFromDatabase()这两个方法
@SuppressWarnings
private
在这两个方法里面会为当前的查询创建一个缓存key,如果缓存中没有值,直接从数据库中读取,执行查询后将得到的list结果放入缓存之中。
紧接着看doQuery()在SimpleExecutor类中重写的方法
public
Statement连接对象就是在这里创建的,因此Executor的作用之一就是创建Statement了,创建完后又把Statement丢给StatementHandler返回List查询结果。
接下来再看一下这里的两个方法prepareStatement()和query()的具体实现
private
public
prepareStatement()是创建Statement的具体实现方法,调用parameterize()对创建的Statement对象设置参数,即为我们设为占位符的地方赋上指定的参数,parameterize()方法再深入进去就是调用ParameterHandler的setParameters()方法具体赋值了。
这里的query()是调用了ResultSetHandler的handleResultSets(Statement) 方法。作用就是把ResultSet结果集对象转换成List类型的集合。
总结以上步骤就是:
- 根据具体传入的参数,动态地生成需要执行的SQL语句,用BoundSql对象表示
- 为当前的查询创建一个缓存Key
- 缓存中没有值,直接从数据库中读取数据
- 执行查询,返回List 结果,然后 将查询的结果放入缓存之中
- 根据既有的参数,创建StatementHandler对象来执行查询操作
- 将创建Statement传递给StatementHandler对象,调用parameterize()方法赋值
- 调用StatementHandler.query()方法,返回List结果集
总结
以上三个步骤所有流程大体可以用一张图来总结
参考
https:// blog.csdn.net/luanlouis /article/details/40422941 https:// blog.csdn.net/a41245184 8/article/details/82723754