一、关于Mybatis的缓存理解
- Mybatis的缓存,包括一级缓存和二级缓存,一级缓存是默认使用的。二级缓存需要手动开启
- 一级缓存指的就是sqlsession 在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。
- 二级缓存指的就是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象
- 图片示例
- 可以看到,对于一级缓存,在一个sqlsession内是通用的,对于二级缓存,可以在多个sqlsession之间公用
-
需要注意的几点:
- Mybatis对缓存提供支持,默认情况下会使用自带的缓存技术,这也就意味着我们可以选择其他的缓存技术
- 通常在没有进行配置的情况下,Mybatis默认开启的是一级缓存,二级缓存需要
二、Mybatis 一级缓存
-
原理
-
分析:
在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库 -
一级缓存的生命周期:
- MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉
- 如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用
- 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用
- SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用
-
示例1
-
示例2
二、Mybatis 二级缓存
1. 原理
- 如图
2. 分析:
- SqlSessionFactory层面上的二级缓存默认是不开启的,二级缓存的开席需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存了,如果我们配置了二级缓存就意味着
- 映射语句文件中的所有select语句将会被缓存
- 映射语句文件中的所欲insert、update和delete语句会刷新缓存
- 缓存会使用默认的Least Recently Used(LRU,最近最少使用的)算法来收回
- 根据时间表,比如No Flush Interval,(CNFI没有刷新间隔),缓存不会以任何时间顺序来刷新
- 缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用
- 缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全的被调用者修改,不干扰其他调用者或线程所做的潜在修改
3. 使用注意:
- 手动开启
- 设置返回POJO类型必须为可序列化
- 实现Serializable接口
4. 测试例子
-
开启二级缓存开关
-
PO的Mapper中配置二级缓存
-
PODO 序列化
-
测试
四、总结
- 二级缓存应用场景
- 对于访问响应速度要求高,但是实时性不高的查询,可以采用二级缓存技术。
- 注意:在使用二级缓存的时候,要设置一下刷新间隔(cache标签中有一个flashInterval属性)来定时刷新二级缓存,这个刷新间隔根据具体需求来设置,比如设置30分钟、60分钟等,单位为毫秒
- 二级缓存局限性:
- Mybatis二级缓存对细粒度的数据,缓存实现不好
- 对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次查询都是最新的商品信息,此时如果使用二级缓存,就无法实现当一个商品发生变化只刷新该商品的缓存信息而不刷新其他商品缓存信息,因为二级缓存是mapper级别的,当一个商品的信息发送更新,所有的商品信息缓存数据都会清空
- 解决此类问题,需要在业务层根据需要对数据有针对性的缓存。比如可以对经常变化的 数据操作单独放到另一个namespace的mapper中