mybatis缓存(了解)
声明
本文为其他博主文章总结,仅用作个人学习,特此声明
参考文章链接
(3条消息) 狂神说 | Mybatis完整版笔记_小七rrrrr的博客-CSDN博客_狂神说mybatis笔记
缓存(了解)
查询:连接数据,耗资源! 一次查询的结果,给他暂存在一个可以取到的地方! ---> 内存 : 缓存 我们再次查询相同数据的时候,直接走缓存,就不用走数据库了。
1.什么是缓存[Cache]?
- 存在内中的临时数据
- 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题
2.为什么使用缓存?
- 减少和数据库的交互次数,减少系统开销,提高系统效率
3.什么样的数据能使用缓存?
- 经常查询并且不经常改变的数据【可以使用缓存】
Mybatis包含一个非常强大的查询缓存特性,它可以非常方便的定制和配置缓存。缓存可以极大的提升查询效率。
Mybatis系统默认定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称本科缓存)
- 二级缓存需要手动开启和配置,它是基于namespace级别的缓存
- 为了提高扩展性,Mybatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
缓存原理如下图所示
1. 一级缓存
-
开启日志
-
测试一个session中查询两次相同记录。
public class MyTest { @Test public void test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUser(1); System.out.println(user); System.out.println("============="); User user1 = mapper.queryUser(1); System.out.println(user1); System.out.println(user == user1); sqlSession.close(); } }
-
查看日志输出
以下情况缓存会失效:
1.查询不同的数据内容
public class MyTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUser(1);
System.out.println(user);
System.out.println("=============");
User user1 = mapper.queryUser(2);
System.out.println(user1);
System.out.println(user == user1);
sqlSession.close();
}
}
2.映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
public class MyTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUser(1);
System.out.println(user);
mapper.UpdateUser(new User(2,"asas","12345678"));
System.out.println("=============");
User user1 = mapper.queryUser(1);
System.out.println(user1);
System.out.println(user == user1);
sqlSession.close();
}
}
3.查询不同的mapper.xml
4.手动清除缓存
public class MyTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUser(1);
System.out.println(user);
sqlSession.clearCache();
System.out.println("=============");
User user1 = mapper.queryUser(1);
System.out.println(user1);
System.out.println(user == user1);
sqlSession.close();
}
}
一级缓存默认开启,只在一次sqlseesion中有效,一级缓存就是一个map
2. 二级缓存
1、什么是二级缓存
- 二级缓存也叫全局缓存,一级缓存作用于太低,所以诞生了二级缓存;
- 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
- 工作机制
- 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
- 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
- 新的会话查询信息,就可以从二级缓存中获取内容
- 不同的mapper查出的数据会放在自己对应的缓存(map)中
2、测试二级缓存
1.开启全局缓存
<setting name="cacheEnabled" value="true"/>
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
---|
2.在要使用二级缓存的Mapper中开启
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
3.测试
public class MyTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUser(1);
System.out.println(user);
sqlSession.close();
//关掉第一个sqlsession才会将一级缓存中的数据保存到二级缓存中
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user1 = mapper1.queryUser(1);
System.out.println(user1);
System.out.println(user == user1);
sqlSession1.close();
}
}
3、小结
- 只要开启了二级缓存,只在同一个Mapper下有效
- 所有的数据都会先放在一级缓存中;只有当会话提交或者关闭的时候,才会提交到二级缓存中
需要注意的是:只用cache时要加序列化
<cache/>
实体类
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private int id;
private String name;
private String pwd;
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
}
3. 自定义缓存-ehcache
Ehcache是一种广泛使用的开源Java分布式缓存,主要面向通用缓存
要在程序中使用ehcache:
1.导入依赖
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.0</version>
</dependency>
2.ehcache的配置文件ehcache.xml
<?xml version="1.0" encoding="UTF8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--
diskStore :为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置,参数解释如下:
user.hoeme - 用户主目录
user.dir - 用户当前工作目录
javaio.tmpdir - 默认临时文件
-->
<diskStore path="./tmpdir/Tmp_EhCache/">
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
<!--
defaultCache:默认缓存策略,当cache找不到定义的缓存时,则使用这个缓存策略,只能定义一个
-->
<!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
3.使用ehchache
<!--自定义缓存,用第三方缓存覆盖-->
<cache type = "org.mybatis.caches.ehcache.EhcacheCache"/>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律