Mybatis的二级缓存剖析

前言:

研究Mybatis的二级缓存需要去扒拉下人家的源代码,研究Mybatis提供的官方jar包;
研究方向万变不离其宗,就算不去看人家的源代码,我们猜一猜也能猜到个大概,大概是用map缓存,
然后用整串的sql+参数作为key,然后查询结果作为value,至于是不是我们可以后面再瞅瞅。

Mybatis源代码开启

在这里插入图片描述
我们主要看两块儿,一块儿是Cache,一块儿是CacheIngExecutor

Cache:数据结构的定义

数据结构分析
核心接口:Cache

在这里插入图片描述

贴出来就是让你看看,里面没啥干货

真正的数据结构来了:PerpetualCache

在这里插入图片描述
你看,是不是验证了我的设想,就是用了一个map来存储

然后我们会发现cache包下面还有一个东西叫decorators

他的实现方式有很多种,很好奇,为毛用这么多的实现,其实实现这么多只是使用了一个装饰者模式,目的是为了给缓存加上各种装饰

在这里插入图片描述
decorators,单词的意思叫装饰,很自然的就会想到设计模式里的装饰者模式,如果读者不了解装饰者模式的可以先去了解下然后往下阅读

FifoCache
LoggingCache
LruCache
ScheduledCache
SerializedCache
SoftCache
SynchronizedCache
TransactionalCache
WeakCache
BlockingCache

我们看到LogginCache,猜想下就是日志,SoftCache 软引用 WeakCache 弱引用 FifoCahce 先进先出,一看就是给缓存加上了一些功能,就是通过装饰者模式给缓存加上各种不同的自定义功能。

可以简单的看下其中某一个装饰者
在这里插入图片描述

在这里插入图片描述

可以看到都是里面包含了一个Cache,然后层次的递进引用,引用到最后一波就是PerpetualCache,反过来可以看到拿最基础的PerpetualCache一层一层的给他包裹新功能,这就是装饰者模式的典型的应用场景
,数据结构到此基本上结束了。

CachingExecutor:缓存调用

核心代码就是下面的这段,建议大家自己打个断点就能理解的更形象一点,我这边文字描述的再详细毕竟只是我自己的理解

 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
            throws SQLException {
        // 将mapper.xml信息加载后形成Cache
        Cache cache = ms.getCache();
        if (cache != null) {
            // 判断是否需要刷新缓存,比如插入等会破坏缓存的行为或者缓存时间过期等都需要刷新
            flushCacheIfRequired(ms);
            //判断缓存是否开启 对应mapper中的cache标签是否配置
            if (ms.isUseCache() && resultHandler == null) {
                //这段可以跳过,是一种校验,感兴趣的可以去搜搜,不影响主干
                ensureNoOutParams(ms, parameterObject, boundSql);
                @SuppressWarnings("unchecked")
                //获取缓存的结果集
                List<E> list = (List<E>) tcm.getObject(cache, key);
                if (list == null) {
                	//为空那就需要放到缓存里了
                    list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                    tcm.putObject(cache, key, list); // issue #578 and #116
                }
                return list;
            }
        }
        // 委托模式,交给SimpleExecutor等实现类去实现方法 如果没有缓存那就得去自己跑了
        return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

简单的调用基本上就结束了,大道至简不是么,恭喜毕业,剩下的细节大家自己带铁锹挖,只是领你入门。

Mybatis二级缓存使用的很多注意事项:

1 基础Bean必须要实现序列化接口
2 查询条件要谨慎,如果不消息用了一个动态的参数,比如当前时间,那么就不适合,因为实时改变,key一直变,这时候你加了缓存,性能会变差

总结:如果基础bean没有实现序列化接口或者是第二种情况,缓存均不会生效,这时候你开启了缓存,但是缓存没卵用,性能反而会降低。

参考资料

CachingExecutor描述的引用更详细点

SprngBoot中如何使用二级缓存

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值