前言:
在了解mybatis的缓存之前我们先了解下Mybatis的几个核心概念
SqlSession:代表着和数据库的一次对话,向用户提供数据库的方法
MapperedStatement:代表着向数据库发送的指令,宏观上可以理解为Sql
Executor:用来和数据库的交互执行器,接受MappereStatement的参数
mybatis的缓存分为一级缓存和二级缓存。
mybatis的默认情况下是开启一级缓存,一级缓存的引用范围是在同一个SqlSession上。在参数和Sql相同的情况下,第一次 的查询结果后会保存到缓存中,当我们使用同一个SqlSession调用同一个接口的情况下,会根据Sql和参数去缓存中获取数 据。如果存在的情况下,将不会去数据库中访问数据。这样降低了数据库的请求压力。
如何验证是否有一级缓存
打开mybatis的showSql的情况下,执行相同的一段代码。
goodsMapper.selectById(1L);
goodsMapper.selectById(2L);
如果只出现了一次Sql查询,这样就证明从一级缓存中获取数据了。
一级缓存的生命周期
1. 一个SqlSession对象中拥有一个新的Executor对象
2.一个Executor对象拥有一个PerpetualCache对象
3.调用SqlSession的Close方法,Excecutor对象和PerpetualCache对象全部销毁不可用
4.调用SqlSession的CloseCache方法,PerpetualCche对象的数据清空。对象可用
5.SqlSession执行update,insert,delete方法的时候,清空缓存数据,对象可用。
SqlSession查询的时序图
整个流程是这样的:
* 针对某个查询的statement,生成唯一的key
* 在Local Cache 中根据key查询数据是否存在
* 如果存在,则命中,跳过数据库查询,继续往下走
* 如果没命中:
* 去数据库中查询,得到查询结果
* 将key和查询结果放到Local Cache中
* 将查询结果返回
* 判断是否是STATEMENT级别缓存,如果是,则清除缓存
总结一级缓存:
1. 一级缓存默认开启,
2. 作用在SqlSession对象上,
3. 保存在SqlSession->Executor执行器->PerpetualCache对象里
4. 可能会出现脏数据查询。(A sqlSession 查询之后进行缓存,B sqlSession 进行Update,A sqlSession 再次查询的数据 为 B 提交之前的数据。缓存不会更新)
5. mybaits和Spring整合时,进行Mapper代理开发的时候。每次SqlSession都会被及时的关闭
mybatis的二级缓存默认是关闭的,并且建议不开启二级缓存,二级缓冲是Application级别的缓存。作用是一级缓存一样
为了解决数据库层的请求压力
开启二级缓存的要求:
1.mybatis返回的POJO对象必须是可序列化的。
2.查询使用频率较多的情况下。
二级缓存的规则
1.映射语句中的所有文件Select语句全部会被缓存
2.映射语句中的所有文件update,delete,insert全部将清空缓存
3.使用LRU(最长未使用原则)来进行回收缓存(另外几个缓存算法,LFU 最少使用原则,FIFO 先进先出原则)
开启二级缓存的方法
<settings>
<!-- 对在此配置文件下的所有cache进行全局性的开/关设置。默认值:true -->
<setting name="cacheEnabled" value="true"/>
</settings>
总结:
1.二级缓存作用在Application级别上。
2.在同一个namespace下的mapper可以共有缓存
3.用二级缓存还不如使用redis,membercache 等 内存数据库。
参考的几篇文章:
https://baijiahao.baidu.com/s?id=1589029405734578119&wfr=spider&for=pc
https://www.cnblogs.com/51life/p/9523926.html
https://www.cnblogs.com/happyflyingpig/p/7739749.html