MyBatis - 基础学习10 - 缓存
一.简介
1.为什么要使用缓存:
我们在数据库查询数据的时候,总会不断的连接,释放,但是使用的查询语句和要查询的东西却是一摸一样的,这样反复的操作是十分浪费资源的
所以,我们在第一次查询出来的结果就可以先存在一个地方,比如用户的内存中:这就是缓存
我们想要再次进行查询的时候就可以直接去缓存,不再直接去数据库,降低了反复连接释放的资源消耗
2.什么是缓存(Cache)
存在内存中的临时数据
将用户经常查询的数据放在内存中,用户去查询数据就不需要从磁盘上(关系数据库文件查询了),直接从内存查询,提高查询效率,解决并发的问题
3.什么样的数据使用缓存
经常查询且不易改变的数据
4.mybatis缓存
mybatis包含一个非常强大的查询缓存特性,它可以非常方便的定制缓存。缓存可以极大的提升查询效率。
mybatis系统默认定义了两级缓存:一级缓存和二级缓存
默认情况下,只有一级缓存开启(sqlsession级别的缓存,也称为本地缓存)
二级缓存需要手动开启和配置,也是基于namespace级别的缓存
为了提高拓展性,mybatis定义了缓存接口Cache,我们可以通过实现Cache实现开启二级缓存
- LRU – 最近最少使用:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。(队列)
二.一级缓存
一级缓存默认开启,一般是一个sqlsession开启到关闭的区间
测试1:
@Test
public void TestselectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.selectUser(1);
System.out.println(user1);
System.out.println("--------------------------------------");
User user2 = mapper.selectUser(1);
System.out.println(user2);
System.out.println(user1==user2);
sqlSession.close();
}
上面的sql语句我们两次查询的都是相同的sql语句,我们使用日志查看一下他会怎么进行操作
从日志中我们可以看到,它只进行了一次连接数据库,因为它在一级缓存内,且查询的东西是一个,所以就不会再一次连接数据库,而是重缓存中拿数据
测试2:
@Test
public void TestselectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.selectUser(1);
System.out.println(user1);
System.out.println("--------------------------------------");
User user2 = mapper.selectUser(2);
System.out.println(user2);
System.out.println(user1==user2);
sqlSession.close();
}
代码和上一次的没什么大区别只是我们的查询对象由两个相同的变成一个查询一号,一个查询二号,那么结果如何呢
很明显的这次由于没有查询相同的数据,他就很难的重新去缓存中拿数据,而是去了数据库拿数据
测试3:
@Test
public void TestselectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.selectUser(1);
System.out.println(user1);
sqlSession.clearCache();
System.out.println("--------------------------------------");
User user2 = mapper.selectUser(1);
System.out.println(user2);
System.out.println(user1==user2);
sqlSession.close();
}
代码中查询的数据都是一样的,理论上第二次查询就会去缓存,但是我们在第一次查询后使用了sqlsession.clearcache()清空一级缓存,结果如何呢
一样的,即使查询数据一样,但清空了一级缓存后,依旧要重新去数据库查询。
值得一提的是,与sqlsession.clearcache()方法有相同的效果就是,我们对数据库进行了 增 删 改 都会使缓存,因为缓存不知道你到底改了你要已经缓存了的数据没有
所以他会进行了 增 删 改 后缓存自动失效
缓存失效情况:
- 1.查询不同的数据
- 2.增删改操作,可能会改变原来的数据,所以会刷新
- 3.查询不同mapper.xml(高于二级缓存了都,一级缓存肯定使用不了)
- 4.手动清理缓存:clearcache()
三.二级缓存
我们在没有开启二级缓存的时候,当一次sqlsession连接断开后,在查相同数据就会端断开连接,但是开启二级缓存后,我们就可以继承上次sqlsession的缓存,然后存在于一次mapper.xml中
@Test
public void TestselectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.selectUser(1);
System.out.println(user1);
sqlSession.close();
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user = mapper1.selectUser(1);
System.out.println(user);
sqlSession1.close();
}
例如以上代码,开启了两次sqlsession,没有开启二级缓存的情况下就会是两次连接和查询数据库
很明显的是可以清楚的看到有两次连接和sql查询,这就是没有开启二级缓存的情况
现在我们来开启二级缓存测试
首先我们先完成几步操作
1.在核心配置文件config.xml中,显示的配置开启二级缓存,主要是提高代码的可读性
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--显示的设置开启二级缓存的权限,mybatis默认是开启,提高代码可读性,因为别人不知道你到底开启了没有--> <setting name="cacheEnabled" value="true"/> </settings>
2.在对应的mapper.xml中开启权限
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
eviction:缓存策略,FIFO,队列,先进先出
flushInterval:刷新间隔,60000=60s
size:最多可以放512个缓存
readOnly:只能读吗
3.测试
@Test
public void TestselectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.selectUser(1);
System.out.println(user1);
sqlSession.close();
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user = mapper1.selectUser(1);
System.out.println(user);
sqlSession1.close();
}
代码和上一次的未开启二级缓存一致,我们来看看查询的结果
在开启了二级缓存以后,我们的查询就只进行了一次连接和查询,但是我们的代码中写的确实两次连接,这就是二级缓存
注意点:我们需要将实体类序列化,不然会报错;
二级缓存总结:
- 只有开启了二级缓存,在同一个mapper才会有效
- 所有缓存数据最开始是放在一级缓存中的
- 只有当会话提交,或者会话关闭的时候才会触发二级缓存
四.自定义缓存
1.依旧是导包(maven就完了)
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.2.1</version> </dependency>
2.自定义缓存在resources中新建一个ehcache.xml用于自定义缓存
<?xml version="1.0" encoding="UTF-8" ?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <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>
然后再对应的mapper.xml中去实现连接:
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
3.测试
自定义缓存没什么好测试的,结果都一样,根据自己的需求设计就行了,但是一般用不到
数据库一般只用于增删改查
redis处理缓存会更加专业 K-V
=============================================================================
完结撒花