MyBatis(2)一级缓存源码解析

MyBatis一级缓存源码解析

本文将探讨一级缓存命中场景以,一级缓存源码实现

MyBatis缓存概述

myBatis中存在两个缓存,一级缓存和二级缓存。

  • 一级缓存:也叫做会话级缓存,生命周期仅存在于当前会话,不可以直接关关闭。但可以通过flushCache和localCacheScope对其做相应控制。

  • 二级缓存:也叫应用级性缓存,缓存对象存在于整个应用周期,而且可以跨线程使用。

关于二级缓存将在后续章节,详细说明。文本先聚焦一级缓存。首先来看如何才能命中一级缓存。

一级缓存的命中场景

关于一级缓存的命中可大致分为两个场景,满足特定命中参数,第二不触发清空方法。

缓存命中参数:

  1. SQL与参数相同:

  2. 同一个会话:

  3. 相同的MapperStatement ID:

  4. RowBounds行范围相同:

触发清空缓存

  1. 手动调用clearCache

  2. 执行提交回滚

  3. 执行update

  4. 配置flushCache=true

  5. 缓存作用域为Statement

一级缓存源码解析

回顾上节课内容,MyBatis执行过程如下图:

本文所要论述的一级缓存逻辑就存在于 BaseExecutor (基础执行器)里面。当会话接收到查询请求之后,会交给执行器的Query方法,在这里会通过 Sql、参数、分页条件等参数创建一个缓存key,在基于这个key去 PerpetualCache中查找对应的缓存值,如果有主直接返回。没有就会查询数据库,然后在填充缓存。

另外通过上图你也看了,最终缓存的实现非常简单,就是一个HashMap。

一级缓存的清空

缓存的清空对应BaseExecutor中的 clearLocalCache.方法。只要找到调用该方法地方,就知道哪些场景中会清空缓存了。

  • update: 执行任意增删改

  • select:查询又分为两种情况清空,一前置清空,即配置了flushCache=true。2后置清空,配置了缓存作用域为statement 查询结束合会清空缓存。

  • commit:提交前清空

  • Rolback:回滚前清空

注意:clearLocalCache 不是清空某条具体数据,而清当前会话下所有一级缓存数据。

MyBatis集成Spring后一级缓存失效的问题?

很多人发现,集成一级缓存后会话失效了,以为是spring Bug ,真正原因是Spring 对SqlSession进行了封装,通过SqlSessionTemplae ,使得每次调用Sql,都会重新构建一个SqlSession,具体参见SqlSessionInterceptor。而根据前面所学,一级缓存必须是同一会话才能命中,所以在这些场景当中不能命中。

怎么解决呢?给Spring 添加事物 即可。添加事物之后,SqlSessionInterceptor(会话拦截器)就会去判断两次请求是否在同一事物当中,如果是就会共用同一个SqlSession会话来解决。

06-02 153
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值