mybatis缓存,包含一级缓存与二级缓存,包括ehcache二级缓存

twz123      2022-05-09     258

关键词:

一,引言

首先我们要明白一点,缓存所做的一切都是为了提高性能明白了这一点下面我们开始进入正题。

二,mybatis缓存概要

①、mybatis的缓存有两种,分别是一级缓存和二级缓存。两者都属于查询缓存,也就是只有执行查询操作的时候才起缓存作用,对于增删改操作无效。

②、一级缓存默认开启,二级缓存默认关闭

③、两者都可以使用SqlSession对象的commit()方法更新缓存。(你肯定是对数据修改才会commit,而数据修改了,则缓存必然要更新,否则会发生类似"脏读"的现象)。

④、二级缓存分为mybatis自带的与第三方提供的两种。三方提供的比较常用的是ehcache。

⑤、二级缓存不同于一级缓存,前者是序列化操作,也就是说二级缓存是存放在硬盘中的。而一级缓存是存放在内存中的。

 

下面开始详细介绍一二级缓存。

三,一级缓存

mybatis的一级缓存是默认开启的,它将数据存放在同一个SqlSession对象中。该对象可以粗略的将其理解为"封装好的数据库连接"。

当我们进行查询操作时,比如:select * from person where name ="张三"  

mybatis会先检查SqlSession对象中是否存在,如果存在,则直接在缓存中获取;否则将从数据库中查找,并将找到的值缓存到SqlSession对象中。

由于此处我还未讲述二级缓存,因此先暂时忽略二级缓存的情况,在下文中我会介绍一二级缓存同时使用的情况。

1 Reader reader = Resources.getResourceAsReader("mybatis-config.xml");

2 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);

3 SqlSession session = sessionFactory.openSession();

更新一级缓存:当我们执行SqlSession对象的commit()时,SqlSession对象中的缓存数据会更新。session.commit();但是由于一级缓存是在内存,不需要序列化,因此它是自动更新的,无需我们手动commit()更新缓存。二级缓存则不然,下文会有介绍。

四,mybatis二级缓存

mybatis的二级缓存是默认关闭的,如果想要使用二级缓存,我们需要在mybatis-config.xml文件中手动配置开启。

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

开启二级缓存之后我们还需要在对应的映射文件中加入<cache/>节点声明该映射文件使用二级缓存。比如我想要对peronMapper.xml使用,则在该文件中加上<cache/>节点。

与一级缓存不同的是,二级缓存的数据缓存在同一个namespace生成的映射对象中。

请牢记这句话,同一个namespace。

1 //就算使用不同的SqlSession对象,只要该对象是同一个mapper映射对象,则它们共享同一个二级缓存
2 PersonMapper p1 = session1.getMapper(PersonMapper.class); 
3 PersonMapper p2  = session2.getMapper(PersonMapper.class);
4 //p1和p2无法共享一级缓存,但可以共享二级缓存

又由于二级缓存是序列化操作,缓存存放在外存,因此涉及到的实体类需要实现序列化接口serializable

1 public class Person implements Serializable{//序列化接口
2     private int id;
3     private String name;
4     private int age;
5     ...........    
6 }

 

其次,因为序列化操作的I/O开关比较频繁的话会严重影响性能,所以mybatis让我们手动序列化缓存(也就是有内存输出到外存),而不是你每次查询之后,它自动帮你将缓存序列化出去

因此我们需要使用SqlSession对象的close()方法手动序列化。close()方法类似于关闭连接。

session.close();//手动序列化二级缓存

如果你不手动序列化,则二级缓存是不会生效的哦。(二级缓存存在于外存,如果你不序列化,则仍然停留在内存中,其他的查询在外存中无法找到,因此无法生效)。

更新二级缓存:①与一级缓存类似,可以使用commit()方法手动更新二级缓存。②如果仔细阅读了上文,你其实不难发现,session.close()操作也是更新二级缓存的操作。

禁用二级缓存:由于<cache/>节点开启了整个mapper文件的二级缓存能力,而可能会有某些sql节点可能不需要用到二级缓存,这是就会造成浪费,此时我们可以使用useCache="false"属性来关闭该sql节点的二级缓存能力。

五,总结

一二级缓存已经初步讲完了,我们将一个一二级缓存同时工作的具体流程来作为总结。

现在当我们执行一个查询操作时:select *from person where name ="张三" 

会先在SqlSession对象中检查是否存在着上次执行同一个sql,已经缓存好的数据(一级缓存),如果存在则直接获取。如果不存在,则再检查同一个namespace产生的mapper对象中是否存在,如果存在,则直接获取。否则将会在数据库中查找。然后将其缓存如SqlSession对象中,和其同一个namespace产生的mapper对象中。需要注意的是,此时二级缓存还没有序列化到外存中,只是在该对象中缓冲起来了,需要你手动调用close()或commit()方法手动序列化到外存中

六,第三方缓存

上文提到过,mybatis的二级缓存分为它自带的与第三方公司提供的两种。(mybatis毕竟不是专业做缓存的,有一些专门研究缓存的公司)。

常见的三方缓存有ehcache、memcache。如果想要使用三方缓存、或自定义缓存,则必须实现mybatis提供的Cache接口(这是必然的,接口是规范)。该接口有很多实现类,默认使用的实现类是PerpetualCache。

在这里我们以ehcache为例来对三方二级缓存进行讲解。

首先需要知道,第三方,第三方,既然是第三方那么肯定需要额外导入jar包。

因此整合ehcache二级缓存需要用到的jar包有:ehcache.jar、mybatis-ehcache.jar、slf4j-api.jar(日志jar,ehcache内置的日志不是log4j)

其次,我们需要编写第三方缓存的配置文件,比如这里的ehcache缓存配置文件。其文件名约定为Ehcache.xml

配置文件的内容如下:

 1 <!-- 当二级缓存的数据(对象)超过内存限制(maxElementsInMemory最大的缓存对象个数)时,就要存入硬盘 -->
 2 <diskStore path="D:devehcache repository"/>
 3 <!-- 
 4     maxElementsInMemory:设置在内存中缓存对象的最大值
 5     maxElementsOnDisk:设置在硬盘中缓存对象的最大值
 6     eternal:设置缓存是否永远不过期
 7     overflowToDisk:设置当内存满了是否往硬盘中转移
 8     timeToIdleSeconds:当2次访问超过该值(秒)的时候,缓存对象失效
 9     timeToLiveSeconds:缓存对象的生存时间(秒)和timeToIdleSeconds差不多
10     diskExpiryThreadIntervalSeconds:每经过多长时间(s)就开启一个线程将硬盘中的缓存清除
11     memoryStoreEvictionPolicy:当超过缓存对象的最大限制时,采取的策略(删除最后面的或删除最前面的等等)。
12                 LRU是操作系统中内存管理的一个算法,意思是Least recently used,最近最少使用。
13                 FIFO:队列,先进先出
14                 LFU:最不常使用
15 -->
16 <defaultCache
17     maxElementsInMemory="1000"
18     maxElementsOnDisk="1000000"
19     eternal="false"
20     overflowToDisk="false"
21     timeToIdleSeconds="100"
22     timeToLiveSeconds="100"
23     diskExpiryThreadIntervalSeconds="120"
24     memoryStoreEvictionPolicy="LRU">
25 </defaultCache>

然后开启二级缓存,与上文中的步骤一样,先在mybatis-config.xml配置文件中开启,再通过具体的<cache/>节点指定相应的mapper文件启用。

与mybatis内置二级缓存不同的是,三方二级缓存需要使用type属性指明实现类(java是面向对象的语言,一切的功能都是基于类来实现的)。

语法如下:

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

此条配置声明了使用EhcacheCache类,该类就是ehcache二级缓存的具体实现,点进去也能够发现该类是org.apache.ibatis.cache.Cache接口的实现类。

我们也可以覆盖Ehcache.xml中的配置项,比如我如果要覆盖内存中缓存对象的最大值,则:

1 <cache>
2     <property name="maxElementsInMemory" value="1000"/>
3 </cache>

三方二级缓存和内置二级缓存一样,数据缓存在【同一个namespace】生成的mapper对象中。

也是commit或close更新缓存。

也是useCache="false"禁用缓存。

也会序列化到硬盘,也要实现serializable接口。只不过三方二级缓存是先存入内存,内存存不下了再存入硬盘(可以设置不存入硬盘)。

mybatis-一级缓存与二级缓存

 1.1  什么是查询缓存mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存,和二级缓存。 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个(内存区... 查看详情

mybatis——一级缓存二级缓存

一、Mybatis缓存●MyBatis包含一个非常强大的查询緩存特性,它可以非常方便地定制和配置缓存。绶存可以极大的提升查询效率。●MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存  ○ 默认情况下,只有一级缓存开启... 查看详情

mybatis一级缓存与二级缓存的区别你知道吗(代码片段)

前言Java面试经常问到Mybatis一级缓存和二级缓存,今天就给大家重点详解Mybatis一级缓存和二级缓存原理与区别。Mybatis缓存缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存可以避免频繁与数据库... 查看详情

mybatis一级缓存与二级缓存的区别你知道吗(代码片段)

前言Java面试经常问到Mybatis一级缓存和二级缓存,今天就给大家重点详解Mybatis一级缓存和二级缓存原理与区别。Mybatis缓存缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存可以避免频繁与数据库... 查看详情

mybatis缓存

基本概念一级缓存与session绑定,只存在于session生命周期内,从数据库中查询到的值会保存到一级缓存中,当session关闭后,会保存到二级缓存中,一级缓存默认是开启的。二级缓存存在于sqlSessionFactory生命周期内,多个session共享... 查看详情

mybatis的一级二级缓存?

1)一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当Sessionflush或close之后,该Session中的所有Cache就将清空,默认打开一级缓存。2)二级缓存与一级缓存其机制相同,默认也是采用PerpetualCache,HashMap存储,不同... 查看详情

mybatis的一级二级缓存

1)一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当Sessionflush或close之后,该Session中的所有Cache就将清空,默认打开一级缓存。2)二级缓存与一级缓存其机制相同,默认也是采用Perp... 查看详情

mybatis一级缓存和二级缓存

MyBatis中的缓存一级缓存:  Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中执行两次相同的SQL语句,第一次执行完毕后会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据不再从数据库中查询... 查看详情

源码级mybatis缓存策略(一级和二级缓存)(代码片段)

...们可以避免频繁的与数据库进行交互,进而提高响应速度MyBatis也提供了对缓存的支持,分为一级缓存和二级缓存,可以通过下图来理解:①、一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一... 查看详情

mybatis-缓存机制

MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。 MyBatis系统中默认定义了两级缓存。 一级缓存和二级缓存。 一级缓存:(本地缓存):SqlSession级别的缓存,一级缓存是一致开... 查看详情

mybatis一级缓存,mybatis二级缓存,mybatis缓存失效(代码片段)

Mybatis一级缓存,Mybatis二级缓存,Mybatis缓存失效 ================================©Copyright蕃薯耀 2021-06-24https://www.cnblogs.com/fanshuyao/ 一、SpringBoot整合Mybatis1、pom.xml引入依赖(基于SpringBoot:2.3.12.REL 查看详情

mybatis的二级缓存

文章目录MyBatis的二级缓存MyBatis默认是开启一级缓存的开启MyBatis的二级缓存为什么要开启二级缓存在mybatis的配置文件中进行配置在对应的mapper映射文件中声明相关的DO对象需要实现序列化测试动态代理接口执行更新方法后会清空... 查看详情

mybatis-缓存机制

MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。MyBatis系统中默认定义了两级缓存,一级缓存和二级缓存。–1、默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本... 查看详情

mybatis缓存

MyBatis缓存MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存默认情况下,只有一级缓存开启。(SqlSession级别的... 查看详情

mybatis源码分析五mybatis的缓存

五、MyBatis缓存文章目录五、MyBatis缓存缓存的概念与应用缓存的概念开发一个简单的缓存MyBatis中的缓存设计自定义一个Cache实现类MyBatis中的Cache实现类PerpetualCache装饰器CacheCache如何在MyBatis运行过程应用MyBatis缓存的二层体系一级... 查看详情

mybatis源码分析五mybatis的缓存

五、MyBatis缓存文章目录五、MyBatis缓存缓存的概念与应用缓存的概念开发一个简单的缓存MyBatis中的缓存设计自定义一个Cache实现类MyBatis中的Cache实现类PerpetualCache装饰器CacheCache如何在MyBatis运行过程应用MyBatis缓存的二层体系一级... 查看详情

mybatis查询结果的缓存

MyBatis的缓存指的是缓存查询结果,当以后使用相同的sql语句、传入相同的参数进行查询时,可直接从mybatis本地缓存中获取查询结果,而不必查询数据库。mybatis的缓存包括一级缓存、二级缓存,一级缓存默认是开启的,二级缓存... 查看详情

mybatis基础系列——关联查询延迟加载一级缓存与二级缓存

关本文是Mybatis基础系列的第四篇文章,点击下面链接可以查看前面的文章:mybatis基础系列(三)——动态sqlmybatis基础系列(二)——基础语法、别名、输入映射、输出映射mybatis基础系列(一)——mybatis入门关联查询在进行表... 查看详情