MyBatis缓存配置

一级缓存
缓存

使用缓存可以使应用更快地获取数据,避免频繁的数据库交互,MyBatis将数据缓存设计成两级结构,分为一级缓存、二级缓存:

一级缓存是SqlSession会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存。

二级缓存是Application级别的缓存,它的作用范围是整个应用程序。

一级缓存

一级缓存是MyBatis内部实现的一个特性,用户不能配置,默认情况下自动支持的缓存

MyBatis会在SqlSession对象中创建一个本地缓存(local cache)。对于每一次查询,都会根据查询的条件去本地缓存中查找是否在缓存中,如果在缓存中,就直接从缓存中取出,然后返回给用户;否则,从数据库读取数据,将查询结果存入缓存并返回给用户。

一级缓存的工作流程

一级缓存的生命周期

MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象;当会话结束时,SqlSession对象也一并释放掉;

如果SqlSession调用了close()方法,会释放掉一级缓存,一级缓存将不可用; 

如果SqlSession调用了clearCache(),会清空缓存,但是该对象仍可使用;

在SqlSession中执行了任何一个update操作、insert操作、delete操作,都会清空缓存,但是该对象可以继续使用;

MyBatis中,如果以下条件都一样,那么就认为它们是完全相同的两次查询:

传入的 statementId

查询时要求的结果集中的结果范围

这次查询所产生的最终要传递给JDBC

java.sql.Preparedstatement的Sql语句字符串

传递给java.sql.Statement要设置的参数值

SqlSession的一级缓存性能问题

MyBatis对会话(Session)级别的一级缓存设计的比较简单,就简单地使用了HashMap来维护,并没有对HashMap的容量和大小进行限制。

一级缓存是一个粗粒度的缓存,没有更新缓存和缓存过期的概念

根据一级缓存的特性,在使用的过程中,应该注意以下两点

对于数据变化频率很大,并且要求高时效准确性的数据,我们使用SqlSession查询的时候,可以手动地适时清空SqlSession中的缓存

对于只执行或者频繁执行大范围的select操作的SqlSession对象,SqlSession对象的生存时间不应过长。

二级缓存

MyBatis的二级缓存默认为开启状态,在主配置文件中,settings配置中有一个参数cacheEnable,当把该参数的值设置为false时,可关闭二级缓存

<settings>
    <setting name="cacheEnable" value="false"/>
</settings>
MyBatis的二级缓存是和命名空间绑定的,即二级缓存需要配置在映射文件中,有两种配置方式

为每一个Mapper分配一个Cache缓存对象(使用<cache>元素配置);

多个Mapper共用一个Cache缓存对象(使用<cache-ref>元素配置); 

1、保证二级缓存的全局配置开启,并且使用二级缓存的实体类要实现Serializable接口

2、给UserMapper.xml开启二级缓存,在mapper元素中

<mapper namespace="com.mybatis.mapper.UserMapper">
    <cache/>
    <!-- 其他配置 -->
</mapper>
默认的二级缓存效果如下:

映射语句文件中的所有 select 语句将会被缓存

映射语句文件中的所有 insert,update和delete语句会刷新缓存

缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序来刷新

缓存会存储集合或对象(无论查询方法返回什么类型)的 1024 个引用

缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改

MyBatis主要提供了以下几个刷新和置换策略:

LRU(Least Recently Used):最近最少使用算法,移除最长时间不被使用的对象,这是默认值  

FIFO(First in first out):先进先出算法,移除最先进入缓存中的对象

flushInterval:刷新间隔,会以指定的某一个时间间隔将缓存中的数据清空,不设置时仅仅在调用语句时刷新

size:可以缓存的对象数目,默认值为1024

readOnly:只读属性,只读的缓存会给调用者返回缓存对象的相同实例,因此这些对象不能被修改;可读写的缓存会返回缓存对象的拷贝,这种方式更安全,因此默认值是false

以上效果都可以通过cache元素的属性来修改:
<cache
    eviction="FIFO"
    flushInterval="60000"
    size="512"
    readOnly="true"/>

这个配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存储结果对象的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突 .

如果想让多个Mapper公用一个Cache缓存,可以使用<cache-ref namespace="">元素配置参照缓存,这样不仅能减少配置项,还能解决脏读问题

MyBatis中开启二级缓存之后,一级缓存和二级缓存的使用顺序为:二级缓存->一级缓存->数据库

集成EhCache缓存 

MyBatis对二级缓存的设计非常灵活,在MyBatis中使用二级缓存有三个选择

它自己内部基于HashMap实现了一系列的Cache缓存实现类,并提供了各种缓存刷新策略如LRU,FIFO等

MyBatis还允许用户自定义Cache接口实现,然后将Cache实现类配置在<cache  type="">type属性上即可

MyBatis还支持第三方缓存框架(EhCache、Redis)的集成

EhCache是一个纯粹的Java进程内的缓存框架,主要特征

快速、简单

提供多种缓存策略

缓存数据有内存和磁盘两种

MyBatis集成EhCache框架的步骤为:

添加jar包,并添加到项目的Build Path

在resources目录下添加ehcache.xml配置文件

修改映射接口中的缓存配置

<mapper namespace="com.mybatis.mapper.UserMapper">
    <cache 
        type="org.mybatis.caches.ehcache.LoggingEhcache"/>
    <!-- 其他配置 -->
</mapper>

ehcache.xml配置文件

<ehcache>
    <diskStore path="d:/cache/"/>
    <defaultCache
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"/>
</ehcache>

脏数据的产生和避免

二级缓存中脏数据产生的原因 

通常情况下每个Mapper映射文件都有自己的二级缓存

有些查询需要关联多张表

涉及这多张表的增删改查操作通常不在一个映射文件中

当数据有变化时,多表查询的缓存不一定会清空,这种情况下就会出现脏数据

可以使用参照缓存来避免脏数据的产生,通常是让几个会关联的ER表使用同一个二级缓存
<cache-ref namespace="net.onest.mapper.UserMapper"/>
二级缓存适用场景

以查询为主的应用中,只有尽可能少的增、删、改操作

绝大多数都是单表操作时,很少出现相互关联的情况

如关联的表比较少,可以通过参照缓存进行配置 

 

 

 

 

相关推荐

  1. 第 7 章 MyBatis 缓存配置

    2024-04-08 16:50:01       6 阅读
  2. Mybatis使用缓存配置总结

    2024-04-08 16:50:01       8 阅读
  3. mybatis缓存

    2024-04-08 16:50:01       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 16:50:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 16:50:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 16:50:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 16:50:01       18 阅读

热门阅读

  1. GO - 标准库

    2024-04-08 16:50:01       15 阅读
  2. Hamilton-Jacobi-Bellman (HJB) 方程

    2024-04-08 16:50:01       17 阅读
  3. 第十四届蓝桥杯省赛大学B组填空题(c++)

    2024-04-08 16:50:01       13 阅读
  4. Android Apk签名算法使用SHA256

    2024-04-08 16:50:01       17 阅读
  5. C++ 动态字符串String的介绍及经典用法展示

    2024-04-08 16:50:01       15 阅读
  6. linux知识点

    2024-04-08 16:50:01       13 阅读
  7. 个人网站开发记录(五)二系统后端nodejs

    2024-04-08 16:50:01       13 阅读