java架构之路-(源码)mybatis执行流程源码解析
这次我们来说说Mybatis的源码,这里只说执行的流程,内部细节太多了,这里只能授之以渔了。还是最近的那段代码,我们来回顾一下。
package mybatis; import mybatis.bean.StudentBean;
import mybatis.dao.StudentMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import java.io.IOException;
import java.io.InputStream; public class Test1 { public SqlSession session;
public SqlSessionFactory sqlSessionFactory; @Before
public void init() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
} @Test
public void studentTest() {
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentBean result = mapper.selectUser(1);
System.out.println(result);
session.commit();
} }
就是拿到流文件,也是我们主配置文件,进行流文件解析,传入到build内,构建成一个sqlSessionFactory,再由sqlSessionFactory得到session,拿到mapper,执行sql,完成。
简单的流程应该是这样的,我们来一个稍微专业一点图。
转变为我们的代码大概就是这三步,构建Configuration对象,构建我们的sqlsessionfactory,得到我们的session,得到对应的statement(处理参数和结果)从而得到结果集。
那么我们先从我们一步步来看,先看我们的Configuration对象
Configuration解析:
我们打开Configuration类可以看到,里面很多的属性设置,包括缓存,mapper,插件等等,其实就是把我们的xml标签转化为对象了,这里需要说明一下的是,这个解析过程是把所有的相关的xml都转为Configuration对象了,包括config.xml和mapper.xml。源码太多,我就不粘贴了。我给你看一下我转化完成的。
这里没有什么神秘的,就是一个xml解析的过程,在XMLConfigBuilder类的parse方法,生成了完成的Configuration对象,有兴趣的可以打个断点看一下。
这里要注意的就是里面很多元素是一个对应多个的,很多属性是map和set。顺便收一下里面是由多个构造器来构建的。
MapperAnnotationBuilder为注解方式的构造器,其余都是为Configuration服务的。也就是说在创建Configuration之后很多东西就已经确定了(除了cache)。那么又是如何生成sqlsession的呢。回到我们创建完Configuration对象那句源码上来。
点击build方法进去,我们看到是new DefaultSqlSessionFactory然后把我们的Configuration对象传递进去,也就是说有了Configuration对象也就生成了我们的DefaultSqlSessionFactory对象。DefaultSqlSessionFactory实现了我们的SqlSessionFactory,我们也就得到了SqlSessionFactory。接下来就是我们的sqlsession了
sessionsql解析:
还是老规矩,上个图再看源码,比较好理解。
执行过程大概是这样的。
就是什么意思呢?由DefaultSqlSessionFactory生成一个执行器Executor,下面是由BaseExecutor支撑的,里面包含一些配置和我们的一级缓存(是不是更深入的知道为啥一级缓存生命短了),同时也有一个类似装饰器的CachingExecutor,他的下面也是需要BaseExecutor来支撑的,需要查询时优先查缓存,查询不到回到我们的BaseExecutor来执行。搂一眼源码去,sqlSessionFactory.openSession()方法也就得到了我们的sqlsession,我们进去看一下都写了什么。
里面的95行tx主要是从我们的configuration中拿到一些数据源的配置,也就是我们图中画的来支撑BaseExecutor的配置,来到96行,创建Executor,传入了数据源配置和一个执行类型,这里简单提一嘴,类型主要有三种:SIMPLE(简单), REUSE(可重复使用), BATCH(批量进行),一般我们都用的SIMPLE。我们再进我们的Executor的创建方法看看,他们都做了什么事。
先判断了执行器类型,简单,可重复,批量,613行就是我们的缓存执行器了,外面那个判断就是你是否配置了二级缓存,从而是否配置我们的缓存执行器,底层还是Executor,可以点击进去看看的。
就是说我们由配置文件config.xml,mapper.xml生成了我们的Configuration对象,将Configuration放置在DefaultSqlSessionFactory内,生成了我们的Executor执行器,准备执行SQL。回到主题我们继续看下一部分,最后一个MappedStatement
MappedStatement解析:
记住两个问题,增删改查,可以归类为两种,一种是原来的数据变化-增删改,另一种是原来的数据没有变化-查询。我们的mybatis也是这样来处理的,主要就是query和update两种大类方法。
MappedStatement是由调用Executor执行器前,由configuration对象来构建的。源码在DefaultSqlSession的select***方法内,这里就不详细说了。感兴趣的可以自己去了解一下。我们主要来说执行流程。
执行过程大致是,1.拿到sql;2.拼接参数;3.执行sql;4.封装结果集。我们来看一下具体的源码流程。
我们上面得知,执行器的真正执行都是在BaseExecutor里来执行的,我们在DefaultSqlSession调用的select方法,最后执行了executor.query,只优先走我们的CachingExecutor执行器,如果没有才到我们的BaseExecutor执行器里面来,我们的sql是查询,不需要变动数据,那么我们把断点打在我们的BaseExecutor类的query方法上。
147行是清理我们的一级缓存,如果在mapper.xml配置了清理标签,这里会先清理一级缓存。queryStack表示这个执行器是否正在被使用。
152行开始查询我们的一级缓存,如果为空调用156行,开始我们正式的查询,里面是放入缓存占位置,然后执行查询,清理缓存的占位重新放置缓存,这里说的都是一级缓存了。
总结一下就是:
1.拿到流文件config.xml和mapper.xml;
2.用我们的两个或多个流文件创建一个Configuration对象,(单一职责原则来构建的,很多个构造器来构建的,例如XMLConfigBuilder)
3.将Configuration对象塞给SqlSessionFactoryBuilder类的build方法,构建SqlSessionFactory对象。
4.sqlSessionFactory.openSession()拿到我们的session对象。
5.由session对象和Configuration对象封装参数和结果集映射,产生对应的执行器来,二级缓存执行器和BaseExecutor执行器。
6.由二级缓存执行器CachingExecutor来优先查询二级缓存是否存在,不存在执行BaseExecutor执行器的query或update方法。
7.拿到结果集转换ResultMap,session关闭,写入二级缓存,返回结束。
最进弄了一个公众号,小菜技术,欢迎大家的加入
java架构之路-(源码)mybatis执行流程源码解析的更多相关文章
- mybatis源码/mybatis执行流程源码解析
https://www.cnblogs.com/cxiaocai/tag/%E9%9D%A2%E8%AF%95%E9%A2%98/public SqlSession session; public S ...
- Mybatis执行流程源码分析
第一部分:项目结构 user_info表:只有id和username两个字段 User实体类: public class User { private String username; private ...
- [转帖]java架构之路-(面试篇)JVM虚拟机面试大全
java架构之路-(面试篇)JVM虚拟机面试大全 https://www.cnblogs.com/cxiaocai/p/11634918.html 下文连接比较多啊,都是我过整理的博客,很多答案都 ...
- SpringMVC执行流程源码分析
SpringMVC执行流程源码分析 我们先来看张图片,帮助我们理解整个流程 然后我们开始来解析 首先SpringMVC基于Servlet来运行 那么我们首先来看HttpServletBean这个类 他 ...
- java架构之路-(源码)mybatis基本使用
我们今天先来简单了解一下我们持久层框架,mybatis的使用.而且现在的注解成为趋势,我主要说一下注解方向的使用吧(配置文件也会说) 从使用角度只要是三个部分,mybatis-config.xml,m ...
- java架构之路-(源码)mybatis的一二级缓存问题
上次博客我们说了mybatis的基本使用,我们还捎带提到一下Mapper.xml中的select标签的useCache属性,这个就是设置是否存入二级缓存的. 回到我们正题,经常使用mybatis的小伙 ...
- java架构之路-(spring源码篇)由浅入深-spring实战详细使用
今天我更新了一篇jvm垃圾回收的算法和垃圾回收器的内部逻辑,但是看的人不多啊......貌似大家还是比较喜欢看源码吧,毕竟实战要比理论用的多. 这篇文章不会详细的深入底层源码,只是基于注解和配置来说说 ...
- java架构之路-(SpringMVC篇)SpringMVC主要流程源码解析(上)源码执行流程
做过web项目的小伙伴,对于SpringMVC,Struts2都是在熟悉不过了,再就是我们比较古老的servlet,我们先来复习一下我们的servlet生命周期. servlet生命周期 1)初始化阶 ...
- java架构之路-(spring源码篇)springIOC容器源码解析(上)
我们这次来叭叭一下Spring的源码,这次博客主要来说说Spring源码,先粗略的撸一遍,下篇博客选几个重点去说,由于过于复杂,我也是看了一点点,我们先来过一遍源码,然后上流程图,最后我们再回头总结一 ...
随机推荐
- JavaWeb前端分页显示方法
在前端中我们总会遇到显示数据的问题 - 正常情况分页显示是必须的,这个时候我们不能仅仅在前端进行分页,在前端其实做起分页是很困难的,着就要求我们在后台拿数据的时候就要把分页数据准备好,在前端我们只需要 ...
- 解决树莓派烧录系统后没有boot文件,只出现盘符问题
首先,如果下图情况,说明你没有烧录好,继续向下看 放一张安装成功的图片 出现这个的原因是因为前期没有烧录好,它会回滚到img文件中,如果中途退出,它会写入到img文件中 正确文件大小(Raspbian ...
- zuul 路由网关 微服务架构系统中
在微服务架构中,基本包含以下常见的组件.服务注册与发现.服务消费.负载均衡.断路器.只能路由.配置管理等.一个简单的微服务架构系统如下 一.Zuul简介 Zuul的主要功能是路由转发和过滤器.路由功能 ...
- gcd 和 同余方程(Exgcd)
求关于x的同余方程 ax≡1(mod b) 的最小正整数解. 对于 100%的数据,2≤a,b≤2*109. NOIP 2012 提高组 第二天 第一题 (只看Exgcd的自行跳过这段文字) 先撇开扩 ...
- 类spring ioc 泛型保留
类spring ioc 泛型保留 什么是泛型擦除 Java并不会传递泛型类,举个直观的栗子: @Component public class BaseProvider<T> { publi ...
- springBoot框架分布式部署定时任务重复执行之解决方案
问题描述: 在集群模式部署服务端时,会出现所有的定时任务在各自的节点处均会执行一遍,这显然不符合实际的开发场景,针对这种问题,本文给出一种springboot集成shedlock的解决方案 第一步:引 ...
- 线上调试工具 jvm-sandbox使用
jvm-sandbox使用 1 快速安装 1.1 下载解压 # 下载最新版本的JVM-SANDBOX wget http://ompc.oss-cn-hangzhou.aliyuncs.com/jvm ...
- C#数据结构_树
树的定义是递归的,用树来定义树.因此,树(以及二叉 树)的许多算法都使用了递归. 结点(Node):表示树中的数据元素. 结点的度(Degree of Node):结点所拥有的子树的个数. 树的度(D ...
- MSIL实用指南-生成while语句
本篇讲解怎样生成while语句.while语句是编程语言中很重要的循环语句,它的结构是while(<表达式>) <语句或语句块> 当表达式的结果为true时就一直执行语句或语句 ...
- Fire Balls 05——坦克和子弹的制作以及炮台发射子弹
版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...