博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MyBatis之缓存(一级缓存、二级缓存)
阅读量:4228 次
发布时间:2019-05-26

本文共 2265 字,大约阅读时间需要 7 分钟。

1,        MyBatis的解析

MyBatis的解析工作由XmlConfiguraBuilder类来实现的,它将MyBatis的所有配置信息解析到Configuration中,为之后的使用提供支持。

2,        MyBatis的一级缓存

MyBatis的一级缓存是SqlSession级别的缓存,每个SqlSession都有一个以及缓存。

我们在对数据库进行操作时,会创建一个SqlSession,而具体的操作都交给了Executor执行器来实现的,SqlSession只是MyBatis对外提供的接口,Executor内部维护了一个Cache对象,是实现类PerpectualCache实例,Cache对象保存了query查询的cacheKey和查询结果的映射。cacheKey是由statementId、rowbounds、原始sql语句以及参数生成。

当我们执行查询时,首先通过构造cacheKey,去Cache中查询是否缓存了结果,有则直接返回,没有再去数据库中差,然后将结果保存到Cache中再返回。

一级缓存实际上是使用PerpetualCache来维护的,其内部是通过一个HashMap来实现的

3,        MyBatis的二级缓存

MyBatis的二级缓存是Application级别的缓存,但是MyBatis对其进行了细化,细化为Mapper级别的缓存,每个Mapper有一个Cache,多个Mapper可以通过cache-ref公用一个Cache。使用MyBatis的二级缓存有三种选择:

1,        MyBatis自身提供的缓存实现

2,        用户自定义的Cache接口实现

3,        跟第三方内存缓存库的集成,比如Encache!

开启二级缓存需要三步:

1,        MyBatis全局配置文件中将cacheEnable设置为true;

2,        Mapper文件中设置cache

3,        具体的select的statement配置中设置useCache为true

MyBatis的二级缓存其实是通过对Executor来实现的。使用二级缓存时,SqlSession创建Executor对象时,会为Executor对象加上一个装饰者:CachingExecutor,其实就是创建一个CachingExecutor对象,它是Executor的装饰者,设计模式之装饰模式自己下去看!当进行查询时,首先CachingExecutor先在二级缓存中查找,找到则直接返回,没有找到再让真正的Executor去执行它的操作(一级缓存和数据库查询),最后CachingExecutor会把Executor的返回结果放到缓存中,然后再返回。

对于MyBatis自身提供的缓存实现,MyBatis定义了大量的Cache的装饰器来增强Cache缓存的功能,对于每个Cache而言,都提供了容量限制,通常采用LRU、FIFO、Scheduled来对缓存进行清除。

4,        MyBatis的二级缓存带来的问题

MyBatis的二级缓存是松散的Cache缓存管理和维护,一个Cache对象只能关联到自身Mapper的操作,Mapper之间的缓存关系比较松散,这样会导致一个问题:

       A表、B表,A表的查询关联了B表,这条查询结果放到了MapperA的Cache中,B表的update会清除MapperB的Cache,但是MapperA的Cache缓存了B的这些数据,导致B的更新对MapperA不可见,导致数据错误。

       解决:

1,        A表和B表共用一个Cache,这样可以解决,但是这样会导致缓存的使用效率低,因为两个Mapper的更新操作都会清空Cache,频繁地清空Mapper导致命中率和使用率都变得很低!

2,        某些表执行更新操作后,去清空跟这些表有关联的查询语句造成的缓存。决定清空哪些查询缓存,是在EnhancedCachingManager中维护的:update类型的statementId和select类型的statementId集合的映射!

针对2的解决,可以使用Enhanced-Cache(加强的缓存)插件,Enhanced-Cache插件由两个构建组成:EnhancedCachingExecutor、EnhancedCachingManager。

EnhancedCachingExecutor,其实就是一个针对Executor的拦截器,拦截Executor的query和update操作,

1,        当Executor执行query操作时

1.1   记录下该查询的statementId和CacheKey,将其添加到EnhancedCachingManager中

1.2   记录下该查询的statementId和此statementId所属的Mapper内的Cache缓存对象的引用

2,        当Executor执行update操作时,将update操作的statementId传递给EnhancedCachingManager,让它根据statementId的配置,去清空指定的查询语句所产生的缓存。

EnhancedCachingManager,它维护着一下几样东西:

1,        整个MyBatis的所有查询所产生的CacheKey集合

2,        所有statementId及其对应的Cache缓存对象的引用

3,        update类型的statementId和select类型的statementId集合的映射,用于当执行update操作时,根据此映射决定清空的查询缓存。

转载地址:http://sejqi.baihongyu.com/

你可能感兴趣的文章
云创冬日紫金山踏雪游记
查看>>
西安思源学院电子信息工程学院院长张卫钢一行到访
查看>>
邀请函|欢迎参加2019云创大数据实验平台金融类/电子商务类/数学统计类院校各省总代理招募大会!...
查看>>
云创大数据的2018年!
查看>>
QNX简介
查看>>
MQTT协议基本介绍
查看>>
进程和线程是操作系统基本概念,了解一下
查看>>
SSL与TLS的区别以及介绍
查看>>
对象切割 - 常量引用传递
查看>>
北邮同学面经
查看>>
Effective C++条款16:成对使用new和delete时要采取相同形式
查看>>
sizeof与strlen
查看>>
一个递归+二分法的洗牌程序
查看>>
YUV格式注释
查看>>
一维、二维数组传参
查看>>
判断当前时间的下一秒是多少
查看>>
从文本文件中读取数据排序并输出到文本
查看>>
求一个整数数组中第二大的数
查看>>
删除一个链表中的节点
查看>>
计算机网络面试整理【转】
查看>>