浅析MyBatis执行器原理
文章目录
- 一、执行器在什么位置
- 二、执行器生成源码解析
- 2.1、生成默认执行器
- 三、执行器的结构分析
- 四、完整查询分析
- 4.1、二级缓存
- 4.2、一级缓存
- 4.3、数据库查询
- 4.4、大致执行结构图
- 五、手写代码还原基本骨架
本文大部分代码来自MyBatis源码,你可以对照着源码一起看
一、执行器在什么位置
初学MyBatis时,我们都知道MyBatis是拥有一级和二级两种缓存,并且默认开启一级缓存,二级缓存我们只需要在映射文件中手动配置即可。
<!--开启全局缓存,默认是开启的MyBatis-config.xml-->
<setting name="cacheEnabled" value="true"/><!-- XXXmapper.xml-->
<cache/>
补充一张我初学MyBatis时的图:
此处直接略过缓存相关的特性…
这里主要谈一点,就是我们学习MyBatis时常说的:SQL查询的顺序是,先二级缓存找,再一级缓存找,还是没有,最后再去数据库中查找
那么为什么呢?它背后是怎样利用代码完成的呢?
这里就要引入本文的主角——执行器(Executor)。多线程阶段学习时,也有一个执行器,当然我们这里所说的是MyBatis中的执行器。
基本的查询代码:
public class Demo01 {public static void main(String[] args) throws IOException {//1.根据配置文件构建sqlSessionFactoryString resource = "resources/mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.通过sqlSessionFactory构建SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//3.执行对应的SQLsqlSession.selectOne("org.apache.ibatis.demo.dao.BlogMapper.selectBlog");//4.关闭资源sqlSession.close();}
}
执行器在第二步生成
//2.通过sqlSessionFactory构建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
- 执行器提供了查询,修改,提交事务,回滚事务,清理一级缓存,FlashStatement接口。
- 一个执行器对应一个SqlSession,由Configuration创建
- 它和SQL处理器是一对多的关系
二、执行器生成源码解析
SqlSessionFactory 接口方法
public interface SqlSessionFactory {//默认SqlSession openSession();SqlSession openSession(boolean autoCommit);SqlSession openSession(Connection connection);SqlSession openSession(TransactionIsolationLevel level);//设置指定类型执行器SqlSession openSession(ExecutorType execType);SqlSession openSession(ExecutorType execType, boolean autoCommit);SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType, Connection connection);Configuration getConfiguration();}
这是SqlSessionFactory接口,就执行器部分的讲解,我们可以将接口中的方法分为3类
- 默认方法
- 手动设置执行器类型
- 其他方法
顺便补充执行器的类型:即我们能够设置的执行器的类型参数,是来自下面的枚举类。从这个枚举类可以看出,我们有三种执行器
public enum ExecutorType {//MyBatis有三种执行器,分别是:简单、复用、批量处理。默认使用简单的,来一条处理一条SIMPLE, REUSE, BATCH
}
2.1、生成默认执行器
public class Configuration {...protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;...public ExecutorType getDefaultExecutorType() {return defaultExecutorType;}
}
使用Configuration类中的默认值,作为我们执行器类型,即简单执行器是我们的默认执行器。
拥有默认参数后的后续操作
如果我们需要生成其他的执行器,传入不同参数即可。
然后把生成的执行器作为参数放入到我们的CachingExecutor中,初始化delegate参数
这里先记牢,delegate这个参数的值是我们生成的真实的执行器,后文还会出现
至此,一个被CachingExecutor包裹着的SimpleExecutor创建完成
三、执行器的结构分析
我们已经看到执行器是如何产生的了,接下来就是本文的重点,执行器之间的关系,以及他们和缓存结构之间的联系。
这里涉及的类或接口共6个,先说结论:
- 最底层的三个子类,分别是我们的批量执行器、简单执行器、复用执行器
- BaseExecutor中包含一级缓存的查询,不包含真实的数据库中的查询
- CachingExecutor中包含二级缓存,通过delegate变量延展
- 每个类只完成一件事情
我们都知道,想要查询数据,我们可以直接去数据库中查询,但是总是进行磁盘IO十分影响效率,所以引出缓存查询。由于不同执行器去缓存中查询特性相同,我们就可以把这部分代码抽取出来,放到BaseExecutor抽象父类中。时间久了由于缓存的局限性,我们又引入了一个级别的缓存,并且称它为——二级缓存。MyBatis的开发者使用一个装饰者模式,让两者衔接起来。
我有想过为什么一定要这样写呢?写一个父类,不也可以?
四、完整查询分析
第二步已经生成了对应的执行器,现在我们需要开始执行对应的SQL查询
// 3.执行对应的SQ
sqlSession.selectList("org.apache.ibatis.demo.dao.BlogMapper.selectBlog");
我们调用的selectList方法,他们根据我们传入的参数的多少,不断完善默认值,最终执行query方法。
4.1、二级缓存
我们会发现,这个query方法是有两个实现类。
根据执行器生成的过程我们可以明确,此时我们会进入CachingExecutor,因为我们的执行器是一个被CachingExecutor包裹着的SimpleExecutor
前文让你牢记的delegate变量,这里出现了。她是在创建基本的执行器成功时,将自己作为参数放入到CachingExecutor中完成赋值的。即默认情况下,这里的delegate就是new SimpleExecutor()
。
4.2、一级缓存
第二节分析执行器结构时,说到基本的执行器都有一个公共的父类BaseExecutor,所以我们这里虽然调用的简单执行器,但是会先经过父类的查询方法,自然父类中就可以完成我们的一级缓存的查询。
4.3、数据库查询
自此,我们两重缓存的执行流程已经都走完了,接下来就是去简单执行器中查询对应的SQL。当然如果我们在前面的任何一级缓存中能查询到对应的数据,那么此次查询就会提前返回
4.4、大致执行结构图
五、手写代码还原基本骨架
手写一个测试类,完成上述查询的基本功能,具体代码如下:
浅析MyBatis执行器原理相关推荐
- 面试官:你分析过mybatis工作原理吗?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 Mybatis工作原理也是面试的一大考点,必须要对其非常清晰,这样 ...
- 从源码角度分析 Mybatis 工作原理
作者:vivo互联网服务器团队-Zhang Peng 一.MyBatis 完整示例 这里,我将以一个入门级的示例来演示 MyBatis 是如何工作的. 注:本文后面章节中的原理.源码部分也将基于这个示 ...
- Mybatis底层原理学习(二):从源码角度分析一次查询操作过程
在阅读这篇文章之前,建议先阅读一下我之前写的两篇文章,对理解这篇文章很有帮助,特别是Mybatis新手: 写给mybatis小白的入门指南 mybatis底层原理学习(一):SqlSessionFac ...
- MyBatis运行原理(二)SqlSession对象创建过程分析
PS:这篇博文承接上一篇: MyBatis运行原理(一)SqlSessionFactory对象创建过程分析 在上一篇博文中分析了SqlSessionFactory对象创建的过程,有了SqlSessio ...
- MyBatis(四)MyBatis插件原理
MyBatis插件原理 MyBatis对开发者非常友好,它通过提供插件机制,让我们可以根据自己的需要去增强MyBatis的功能.其底层是使用了代理模式+责任链模式 MyBatis官方https://m ...
- mybatis返回null_面试官:你分析过mybatis工作原理吗?
Mybatis工作原理也是面试的一大考点,必须要对其非常清晰,这样才能怼回去.本文建立在Spring+SpringMVC+Mybatis整合的项目之上. 我将其工作原理分为六个部分: 读取核心配置文件 ...
- mybatis工作原理_万字好文!MyBatis 的工作原理,你了解过吗?
回复 1024 有特别礼包 作者:江南入直 | 来源:cnblogs.com/scuury/p/10371246.html 上一篇:微信支付的架构到底有多牛? 近来想写一个mybatis的分页插件,但 ...
- MyBatis 实现多表查询、resultMap 标签、MyBatis 注解、mybatis运行原理
内容 Auto Mapping 单表实现(别名方式) 实现单表配置 单个对象关联查询(N+1,外连接) 集合对象关联查询 注解开发 MyBatis 运行原理 一.MyBatis 实现多表查询 Myba ...
- MyBatis的原理
MyBatis是一款常用的持久层框架,它支持定制化的SQL.存储过程以及高映射.MyBatis封装了JDBC的代码,可以简单的使用XML或注解来配置和映射原生信息,将接口和Java的普通对象映射成数据 ...
- Mybatis运行原理及源码解析
Mybatis源码解析 一.前言 本文旨在mybatis源码解析,将整个mybatis运行原理讲解清楚,本文代码地址: https://github.com/lchpersonal/mybatis-l ...
最新文章
- UnicodeEncodeError: ‘locale‘ codec can‘t encode character ‘\u5e74‘ in position 2: Illegal byte seque
- 我是如何学习写一个操作系统(三):操作系统的启动之保护模式
- LeetCode:位运算实现加法
- swift基础学习(八)
- Python 使用ntplib库同步校准当地时间的方法 (NTP)
- lightbox的一个ajax效果
- 收集:Hibernate中常见问题 No row with the given identifier exists问题的原因及解决
- 【HDU5869】Different GCD Subarray Query(求[L,R]内有多少个不同的区间gcd---树状数组+思维)
- 梦游计算机,传承与奉献!《梦幻西游》电脑版《梦游敦煌》完结
- 伊朗 2018 ICPC区域赛 A : Iranian ChamPions Cup
- 【软考】PV操作同步互斥
- 关于我的专业(niit软件工程方向)
- webERP安装配置超详细
- 02-leveldb入门
- 软件测试方法和测试策略
- Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储
- 【ospf路由计算(一类LSA-router、二类LSA-Network、三类LSA-sum-Net)】-20211228-30
- SMC压缩空气质量分级及管理——含水量篇
- 信号与系统难点之采样正弦信号的获取问题
- 浏览器调取摄像头拍照并有遮罩层
热门文章
- CF1A Theatre Square
- mysql查询季度数据统计_mysql按年度、季度、月度、周、日SQL统计查询代码
- 电脑中的打印驱动程序如何打包_旧驱动程序会教您如何处理笔记本电脑上的黑屏...
- linux备份文件_aptclone:备份已安装的软件包并在新的 Ubuntu 系统上恢复它们 | Linux 中国...
- html行为样式动作是啥,什么是结构、样式、行为分离?
- 生活中常见物联网实例_包邮赠书| 什么是物联网?常见IoT 物联网协议最全讲解...
- java recv failed,java.sql.SQLException: I/O Error: Software caused connection abort: recv failed
- labview 判断整数_labview教程——如何判断字符串包含的是数字
- mysql master slave模式,mysql复制(Replication)模式 主从(Master Slave)模式
- 程序员必备的css工具,8个提高效率的CSS实用工具