美文网首页
MyBatis(五)缓存

MyBatis(五)缓存

作者: guideEmotion | 来源:发表于2019-07-07 18:58 被阅读0次

一 缓存机制

MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置定制。缓存可以极大的提升查询效率
MyBatis系统中默认定义了两级缓存。一级缓存和二级缓存
– 1、默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
– 2、二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
– 3、为了提高扩展性。 MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

架构图

image.png

二 一级缓存

一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap),用于存储缓存数据。不同的sqlSession之间的缓存区域(HashMap)是互不影响的。

一级缓存(local cache), 即本地缓存, 作用域默认为sqlSession。当 Session flushclose 后, 该Session 中的所有 Cache 将被清空
• 本地缓存不能被关闭, 但可以调用clearCache()来清空本地缓存, 或者改变缓存的作用域.
• 在mybatis3.1之后, 可以配置本地缓存的作用域.
在 mybatis.xml 中配置

两种级别

Mybatis提供了一级缓存的方案来优化在数据库会话间重复查询的问题。实现的方式是每一个SqlSession中都持有了自己的缓存,一种是SESSION级别,即在一个Mybatis会话中执行的所有语句,都会共享这一个缓存。一种是STATEMENT级别,可以理解为缓存只对当前执行的这一个statement有效。Statement,即不使用一级缓存

工作流程

根据一级缓存的工作流程,我们绘制出一级缓存执行的时序图,如下图所示。



主要步骤如下:

  1. 对于某个Select Statement,根据该Statement生成key
  2. 判断在Local Cache中,该key是否用对应的数据存在。
  3. 如果命中,则跳过查询数据库,继续往下走。
  4. 如果没命中:
    4.1 去数据库中查询数据,得到查询结果;
    4.2 将key和查询到的结果作为key和value,放入Local Cache中。
    4.3. 将查询结果返回;
  5. 判断缓存级别是否为STATEMENT`级别,如果是的话,清空本地缓存。

工作场景

image.png
(1). 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
(2). 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。(3). 第二次发起查询用户id为1的用户信息,先去找缓存`中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。mybatis默认支持一级缓存的。测试很简单,这里就不贴代码了。

三 二级缓存

• 二级缓存(second level cache),全局作用域缓存
• 二级缓存默认不开启,需要手动配置
• MyBatis提供二级缓存的接口以及实现,缓存实现要求;POJO实现Serializable接口
二级缓存在 SqlSession 关闭或提交之后才会生效

使用步骤

– 1、全局配置文件中开启二级缓存
<setting name="cacheEnabled" value="true"/>
– 2、需要使用二级缓存的映射文件处使用cache配置缓存cache-ref:cache-ref代表引用别的命名空间的Cache配置,两个命名空间的操作使用的是同一个Cache
• <cache />
– 3、注意:POJO需要实现Serializable接口

映射文件的缓存配置

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache> -->

<cache-ref namespace="mapper.StudentMapper"/>

属性

  • eviction:缓存的回收策略:
    LRU – 最近最少使用的:移除最长时间不被使用的对象。
    • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    • 默认的是LRU
  • flushInterval:缓存刷新间隔
    缓存多长时间清空一次,默认不清空,设置一个毫秒值
  • readOnly:是否只读:
    true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
    mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
    false:非只读:mybatis觉得获取的数据可能会被修改。
    mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢
  • size:缓存存放多少元素;
  • type:指定自定义缓存的全类名;实现Cache接口即可;
  • blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存

流程

当开启二级缓存后,会使用CachingExecutor装饰Executor,在进入后续执行前,先在CachingExecutor进行二级缓存的查询,具体的工作流程如下所示。

image.png
在二级缓存的使用中,一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存是被多个SqlSession共享着的,是一个全局的变量
当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库

不同namespace查出的数据会放在自己对应的缓存中(map)
效果:数据会从二级缓存中获取

  • 查出的数据都会被默认先放在一级缓存中。
  • 只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中

和缓存有关的设置/属性

  • 每个select标签都有useCache="true":false:不使用缓存(一级缓存依然使用,二级缓存不使用)
  • 每个增删改标签的:flushCache="true":(一级二级都会清除):
    增删改执行完成后就会清除缓存
    测试:flushCache="true":一级缓存就清空了;二级会被清除;
    查询标签:flushCache="false":
    如果flushCache=true;每次查询之后都会清空缓存;缓存是没有被使用的

参考

  1. Mybatis学习总结(九)——查询缓存
  2. https://www.jianshu.com/p/c553169c5921

相关文章

网友评论

      本文标题:MyBatis(五)缓存

      本文链接:https://www.haomeiwen.com/subject/ljkihctx.html