mybatis源码介绍(三)

Executor执行器

执行器 Executor 是 MyBatis 的核心接口之一,接口层提供的相关数据库操作,都是基于 Executor 的子类实现的。默认情况下使用缓存的 CachingExecutor 。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。

原理分析

1、在 SqlSessionFactory 创建完成后,调用 openSession 方法,在 SqlSessionFactory 的默认实现类DefaultSqlSessionFactory 可以看到 openSession中调用了 openSessionFromDataSource ,在这个方法中会创建一个执行器,代码如下:
在这里插入图片描述

执行器对象是由 Coniguration 对象负责创建的。Configuration 对象会根据得到 ExecutorType 创建对应的Excecutor 对象,并把这个 Excecutor 对象传给 SqlSession 对象

Executor继承结构

Executor接口:有两个实现类BaseExecutor、CachingExecutor。

BaseExecutor:是一个抽象类,抽象类实现接口是”适配器模式“的体现,为了方便下一级实现类对接口中方法的实现;BaseExecutor 有三个子类分别是 simpleExecutor、ResuseExecutor、BatchExecutor。

  1. SimpleExecutor:是MyBatis中默认使用的执行器. 每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。(可以是Statement或PrepareStatement对象)
  2. ReuseExecutor:可重用执行器,这里的重用指的是重复使用Statement. 它会在内部利用一个Map把创建的Statement都缓存起来,每次在执行一条SQL语句时,它都会去判断之前是否存在基于该SQL缓存的Statement对象,存在而且之前缓存的Statement对象对应的Connection还没有关闭的时候就继续用之前的Statement对象,否则将创建一个新的Statement对象,并将其缓存起来。因为每一个新的SqlSession都有一个新的Executor对象,所以我们缓存在ReuseExecutor上的Statement的作用域是同一个 SqlSession。相同的 SQL 会复用 Statement。
  3. BatchExecutor批处理执行器,.用于将多个sql语句一次性输送到数据库执行.
  4. CachingExecutor:缓存执行器, 先从缓存中获取查询结果,存在就返回,不存在,再委托给Executor delegate去数据库取,delegate可以是上面任一的SimpleExecutor、ReuseExecutor、BatchExecutor
    在这里插入图片描述

ExcecutorType的选择

ExecutorType来决定Configuration对象创建何种类型的执行器.它的赋值可以通过两个地方进行赋值.

首先.可以通过标签来设置当前工程中所有SqlSession对象使用的默认Executour
在这里插入图片描述
也可以通过SqlSessoinFactory中openSession方法来指定具体的SqlSession使用的执行器。
在这里插入图片描述

SelectOne底层原理查询

在这里插入图片描述
1、当查询单条数据的时候,最终还是调用selectList查询多个结果集包装程单个对象。
在这里插入图片描述
在这里插入图片描述
从源码中看出,mybatis 查询数据最多查询 2147483647 条数据。

2、从configuration中获取到MappedStatement(对应的sql语句配置),调用executor的query方法实现执行。
在这里插入图片描述
在这里插入图片描述
先查询二级缓存,是否有缓存,没有的话调用delegate. query
在这里插入图片描述
如果一级缓存中没有该结果,会调用queryFromDatabase查询数据库得到数据让后在缓存到一级缓存中,下次查询的时候相同的sql语句直接走一级缓存不会查询数据库(同一个sqlSession)。

Mybatis一级与二级缓存

一级缓存

mybatis的一级缓存是 SqlSession 级别的缓存,在操作数据库的时候需要先创建 SqlSession 会话对象,在对象中有一个 HashMap 用于存储缓存数据,此 HashMap 是当前会话对象私有的,别的SqlSession 会话对象无法访问。

具体流程:

  1. 第一次执行 select 完毕会将查到的数据写入 SqlSession 内的 HashMap 中缓存起来
  2. 第二次执行 select 会从缓存中查数据,如果 select 相同切传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率

注意事项:

  1. 如果SqlSession执行了DML操作(insert、update、delete),并 commit 了,那么mybatis就会清空当前SqlSession缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读

  2. 当一个SqlSession结束后那么他里面的一级缓存也就不存在了,mybatis默认是开启一级缓存,不需要配置

  3. mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key

注意:服务器集群的时候,每个sqlSession有自己独立的缓存相互之间不存在共享,所以在服务器集群的时候容易产生数据冲突问题。

如何禁用一级缓存?

  • 方案1 在sql语句上 随机生成 不同的参数 存在缺点:map集合可能爆 内存溢出的问题
  • 方案2 开启二级缓存
  • 方案3 使用sqlSession强制清除缓存
  • 方案4 创建新的sqlSession连接。

二级缓存

二级缓存是 mapper 级别的缓存,也就是同一个 namespace 的 mappe.xml,当多个 SqlSession 使用同一个 Mapper 操作数据库的时候,得到的数据会缓存在同一个二级缓存区域,二级缓存默认是没有开启的。

二级缓存回收策略
  • LRU:最近最少使用的策略,移除最长时间不被使用的对象。
  • FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。
  • SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。

软引用与弱引用的区别:

  1. 软引用: 软引用是用来描述一些有用但并不是必需的对象, 对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象
  2. 弱引用: 弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象

源码执行流程

因为mybatis 二级缓存默认没有开启,所以首先需要先开启二级缓存。在mybatis 的配置文件中修改,如下图:

然后,二级缓存是mapper级别的缓存,也就是同一个namespace的mappe.xml。每个mapper.xml文件中也需要配置缓存接口实现类,和配置回收策略。

1、首先会计算出缓存的key
在这里插入图片描述
2、然后会去判断有没有开启二级缓存,开启的话,就去二级缓存中查询,查询不到的话,会去查询一级缓存,一级缓存也没有的话就回去查询数据库了,反之,从缓存中拿到数据就返回了。
在这里插入图片描述
在这里插入图片描述
二级缓存涉及到两个重要的类:TransactionalCache、TransactionalCacheManager

TransactionalCache
TransactionalCache:继承自Cache接口,主要作用是保存SqlSession在事务中需要向某个二级缓存提交的缓存数据(因为事务过程中的数据可能会回滚,所以不能直接把数据就提交二级缓存,而是暂存在TransactionalCache中,在事务提交后再将过程中存放在其中的数据提交到二级缓存,如果事务回滚,则将数据清除掉)
在这里插入图片描述
TransactionalCacheManager
TransactionalCacheManager:用于管理CachingExecutor使用的二级缓存对象,只定义了一个transactionalCaches字段

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值