Mybatis的缓存


Mybatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。

Mybatis 系统中默认定义了两级缓存:一级缓存和二级缓存

  • 默认情况下,只有一级缓存SqlSession级别的缓存、也称作本地缓存
  • 二级缓存需要手动开启和配置,它是基于namespace级别的缓存

一级缓存(本地缓存)

一级缓存作用域默认为SqlSession。同一次会话期间只要查询过的数据都会保存在当前SqlSession的一个Map中。当 Sessionflush 或 close 后, 该Session中的所有 Cache 将被清空。
一级缓存不能被关闭, 但可以调用 clearCache()来清空本地缓存, 或者改变缓存的作用域。


(1)修改缓存作用域

可以在全局配置文件修改一级缓存的缓存作用域
mybatis-config.xml

<settings>
	<setting name="localCacheScope" value="STATEMENT"/>
</settiongs>

在这里插入图片描述

(2)失效的情况

  • 不同的SqlSession对应不同的一级缓存
    如下面的变量 sqlSession 和 sqlSession 1
@Test
public void test() {
	SqlSession sqlSession = MyTest.getSqlSessionFactory().openSession();
	SqlSession sqlSession1 = MyTest.getSqlSessionFactory().openSession();
	EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
	EmployeeMapper mapper1 = sqlSession1.getMapper(EmployeeMapper.class);
	System.out.println(mapper.getEmployeeByDid(2));
	sqlSession.close();
	System.out.println(mapper1.getEmployeeByDid(2));
	sqlSession1.close();
}
  • 同一个SqlSession但是查询条件不同
    如下面调用getEmployeeByDid的输入参数不同
@Test
public void test() {
	SqlSession sqlSession = MyTest.getSqlSessionFactory().openSession();
	EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
	System.out.println(mapper.getEmployeeByDid(1));
	System.out.println(mapper.getEmployeeByDid(2));
	sqlSession.close();
}
  • 同一个SqlSession两次查询期间执行了任何一次增删改操作
    如下面在两次查询方法间执行了删除方法deleteEmployee
@Test
public void test() {
	SqlSession sqlSession = MyTest.getSqlSessionFactory().openSession();
	EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
	System.out.println(mapper.getEmployeeByDid(1));
	mapper.deleteEmployee(3);
	System.out.println(mapper.getEmployeeByDid(2));
	sqlSession.close();
}
  • 同一个SqlSession两次查询期间手动清空了缓存
    如下面调用了clearCache()方法清空缓存
@Test
public void test() {
	SqlSession sqlSession = MyTest.getSqlSessionFactory().openSession();
	EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
	System.out.println(mapper.getEmployeeByDid(1));
	sqlSession.clearCache();
	System.out.println(mapper.getEmployeeByDid(2));
	sqlSession.close();
}

二级缓存

二级缓存全局作用域缓存。

  • 二级缓存默认不开启,需要手动配置
  • MyBatis提供二级缓存的接口以及实现,缓存实现要求 POJO 实现Serializable接口
  • 二级缓存在 SqlSession关闭或提交之后才会生效

(1)步骤

  1. 全局配置文件中开启二级缓存
<settiengs>
	<setting name="cacheEnabled" value="true"/>
</settings>
  1. 需要使用二级缓存的映射文件处使用cache配置缓存
<cache/>
  1. POJO 需要实现 Serializable接口
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String lastName;
    private String email;
    private String gender;
}

(2)cache相关属性

<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>
  • eviction:缓存回收策略:
    • LRU最近最少使用的:移除最长时间不被使用的对象。
    • FIFO先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    • 默认的是 LRU
  • flushInterval:刷新间隔,单位毫秒
    默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
  • size:引用数目,正整数,默认值是 1024。
    代表缓存最多可以存储多少个对象,太大容易导致内存溢出
  • readOnly:只读,属性可以被设置为 true 或 false,默认是 false。
    • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象
      不能被修改。这提供了很重要的性能优势。
    • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,
      但是安全。

缓存相关设置

除了上面提到的setting的子元素cacheEnablesqlSession的方法flushCache(),还有:

  • select标签的useCache属性:
    配置这个select是否使用二级缓存。一级缓存一直是使用的
    <select id="getEmployee" resultType="employee" useCache="true">
    	select * from employee where id = #{id}
    </select>
    
  • sql 标签的flushCache属性:
    增删改默认flushCache=true。sql 执行以后,会同时清空一级和二级缓存。
    查询默认flushCache=false
    <select id="getEmployee" resultType="employee" flushCache="true">
        select * from employee where id = #{id}
    </select>
    

第三方缓存整合

E h C a c h e EhCache EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 H i b e r n a t e Hibernate Hibernate 中默认的CacheProvider

步骤

  1. 导入echcahe需要的包,以及整合包、日志包。

pom.xml

<dependencies>
	<!-- java的线程内缓存框架 -->
	<dependency>
		<groupId>net.sf.ehcache</groupId>
		<artifactId>ehcache-core</artifactId>
		<version>2.6.11</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>2.0.0-alpha5</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-api</artifactId>
		<version>2.0.0-alpha5</version>
	</dependency>
	<dependency>
		<groupId>org.mybatis.caches</groupId>
		<artifactId>mybatis-ehcache</artifactId>
		<version>1.2.1</version>
	</dependency>
</dependencies>
  1. 编写 ehcache.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="E:\ehcache" />
 
<defaultCache 
   maxElementsInMemory="10000" 
   maxElementsOnDisk="10000000"
   eternal="false" 
   overflowToDisk="true" 
   timeToIdleSeconds="120"
   timeToLiveSeconds="120" 
   diskExpiryThreadIntervalSeconds="120"
   memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
 
<!-- 
属性说明:
l diskStore:指定数据在磁盘中的存储位置。
l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
 
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目 
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
 
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
 -->
  1. 配置 cache 标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

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

<!-- 引用缓存:namespace:指定和哪个名称空间下的缓存一样 -->
<cache-ref namespace="com.atguigu.mybatis.dao.EmployeeMapper"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值