【Mybatis学习笔记】—— 【五】缓存机制

需要更好的阅读的体验请移步 👉 小牛肉的个人博客 👈



MyBatis 包含一个非常强大的查询缓存特性,它可以非 常方便地配置和定制。缓存可以极大的提升查询效率。
MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存。

  • 默认情况下,只有一级缓存(SqlSession级别的缓存, 也称为本地缓存)开启。
  • 二级缓存需要手动开启和配置,他是基于namespace级 别的缓存。(也称为全局缓存)
  • 为了提高扩展性。MyBatis定义了缓存接口Cache。我们 可以通过实现Cache接口来自定义二级缓存

1. 一级缓存(本地缓存)

一级缓存(本地缓存):sqlSession 级别的缓存

  • 一级缓存是一直开启的;
  • SqlSession 级别的一个Map
  • 与数据库同一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;

一级缓存失效情况(没有使用到当前一级缓存的情况,还需要再向数据库重新发出sql语句进行查询):

  • sqlSession不同
  • sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)
  • sqlSession相同,两次查询之间执行了增删改操作(因为这次增删改可能对当前数据有影响)
  • sqlSession相同,手动清除了一级缓存(缓存清空) openSession.clearCache();

2. 二级缓存(全局缓存)

二级缓存(全局缓存):基于namespace级别的缓存,一个namespace对应一个二级缓存 <mapper namespace="com.smallbeef.mybatis.dao.EmployeeMapper">

工作机制:

  • 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;

  • 如果会话关闭,一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;(二级缓存只有在 SqlSession 关闭或提交之后才会生效

  • 不同namespace查出的数据会放在自己对应的缓存中(map)

使用:

  • (二级缓存默认不开启,需要手动配置 )在全局配置文件中 开启全局二级缓存配置:
<settings>	
	<!--显式的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题  -->
	<setting name="cacheEnabled" value="true"/>
</settings>
  • mapper.xml 中配置使用二级缓存:<cache></cache>
<mapper namespace="com.smallbeef.mybatis.dao.EmployeeMapper">
	<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>

cache标签的属性:

eviction : 缓存的回收策略:

  • LRU (默认) – 最近最少使用的:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

flushInterval :缓存刷新间隔
缓存多长时间清空一次,默认不清空。单位是毫秒

readOnly : 是否只读:

  • true:只读:mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
    mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
  • false:非只读 (默认):mybatis觉得获取的数据可能会被修改。
    mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢

size :缓存存放多少元素;代表缓存最多可以存储多少个对象,太大容易导致内存溢出

type :指定自定义缓存的全类名;(默认就是 namespace 的名称)

  • 注意: POJO需要实现序列化接口
public class Employee implements Serializable{

}

3. 缓存相关设置

和缓存有关的设置/属性:

  • cacheEnabled=true:开启二级缓存
    false:关闭缓存(二级缓存关闭)(一级缓存仍然可用)

  • 每个 select 标签都有 useCache="true" (默认)
    配置这个select是否使用二级缓存。一级缓存一直是使用的

  • 每个增删改标签默认 flushCache="true":sql执行以后,会同时清空一级和二级缓存。
    查询标签默认 flushCache="false"

  • sqlSession.clearCache(); 清除当前session的一级缓存;

  • 当在某一个作用域 (一级缓存Session/二级缓存 namespace) 进行了增删改 操作后,默认该作用域下所有 select 中的缓存将被 clear。

4. Mybatis 的缓存原理

5. 第三方缓存 EhCache 整合

EhCache 是一个纯Java的进程内缓存框架,具有快速、精 干等特点,是Hibernate中默认的CacheProvider。

整合步骤如下:

导入 ehcache 包,以及Mybatis整合包,日志包

  • ehcache-core-2.6.8.jar
  • mybatis-ehcache-1.0.3.jar
  • slf4j-api-1.6.1.jar
  • slf4j-log4j12-1.6.2.jar

编写ehcache.xml配置文件

该配置文件放在 conf 文件夹下,和 全局配置配置文件 为同级目录

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 <!-- 磁盘保存路径 -->
 <diskStore path="D:\44\ehcache" />
 
 <defaultCache 
   maxElementsInMemory="10000" 
   maxElementsOnDisk="10000000"
   eternal="false" 
   overflowToDisk="true" 
   timeToIdleSeconds="120"
   timeToLiveSeconds="120" 
   diskExpiryThreadIntervalSeconds="120"
   memoryStoreEvictionPolicy="LRU">
 </defaultCache>
</ehcache>
 

属性说明:

  • diskStore:指定数据在磁盘中的存储位置。
  • defaultCache:当借助CacheManager.add(“demoCache”)创建Cache时,EhCache便会采用< defalutCache />指定的的管理策略

以下属性是必须的:

  • maxElementsInMemory - 在内存中缓存的element的最大数目
  • maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
  • eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
  • overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上

以下属性是可选的:

  • timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
  • timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
  • diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
  • diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
  • diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
  • memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)

mapper 中配置 cache标签

<mapper namespace="com.smallbeef.mybatis.dao.EmployeeMapper">
	<cache type= "org.mybatis.caches.ehcache.EhcacheCache"></cache> 

若想在命名空间中共享相同的缓存配置和实例。 可以使用 cache-ref 元素来引用另外一个缓存。

<mapper namespace="com.smallbeef.mybatis.dao.DepartmentMapper">
	<cache-ref namespace="com.atguigu.mybatis.dao.EmployeeMapper"/>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章