缓存
MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在SQL的映射文件中添加一行:
<cache/>
一级缓存
也叫本地缓存 只在一次SqlSession中有效(默认是开启的)
与数据库同一次会话期间查询到的数据会放在本地缓存中
如果以后需要获取相同的数据,可以直接从缓存中拿, 不需要再去查询数据库
失效的情况:
- sqlSession不同
- sqlSession相同,查询不同
- sqlSession相同,两次相同查询之间进行了增删改
- 手动清除了一级缓存
sqlSession.clearCache();
测试步骤
- 开启日志
便于观察查询过程 - 测试在一个SQLsession中查询两次相同记录
@Test
public void test6(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userByID = mapper.getUserByID(1);
System.out.println("userByID = " + userByID);
User userByID2 = mapper.getUserByID(1);
System.out.println("userByID2 = " + userByID2);
System.out.println(userByID2==userByID);
mapper.addUser(new User(11,"李宗盛","lizongsheng"));
mapper.addUser(new User(12,"林忆莲","linyilian"));
User userByID3 = mapper.getUserByID(1);
System.out.println("userByID3 = " + userByID3);
System.out.println(userByID3==userByID);
mapper.deleteUser(5);
sqlSession.close();
}
- 查看日志输出
二级缓存
只要开启了二级缓存,在同一个MApper下就有效
所有的数据都会先放在一级缓存中
只有当会话提交,或者关闭的时候,才会提交到二级缓存中
开启二级缓存步骤:
第一步:在mybatis-config核心配置文件中显式开启全局配置
<settings>
<!-- 显式开启全局缓存 -->
<setting name="cacheEnable" value="true"/>
<!-- 标准日志工厂实现 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- <setting name="logImpl" value="LOG4J"/>-->
</settings>
第二步:mapper.xml中增加cache标签
也可以对每个查询语句设置,一般很少用
第三步:实体类都要实现可序列化接口
public class User implements Serializable {
private int id;
private String name;
private String password;
}
cache中的一些参数(一般也不用)
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
缓存原理
首先,查询会先看二级缓存中有没有,如果没有再看一级缓存,一级缓存也没有就查数据库,查到了后把结果放到一级缓存,待当前会话结束后,一级缓存中的缓存数据会转移到二级缓存中
第三方提供的二级缓存ehcache
第一步:导入依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
第二步:mapper.xml的cache标签里面设置缓存的实现
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
第三步:创建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>
ehcache.xml配置信息 可以去网上搜
diskStore : ehcache支持内存和磁盘两种存储
path :指定磁盘存储的位置
defaultCache : 默认的缓存
maxEntriesLocalHeap=“10000”
eternal=“false”
timeToIdleSeconds=“120”
timeToLiveSeconds=“120”
maxEntriesLocalDisk=“10000000”
diskExpiryThreadIntervalSeconds=“120”
memoryStoreEvictionPolicy=“LRU”
cache :自定的缓存,当自定的配置不满足实际情况时可以通过自定义(可以包含多个cache节点)
name : 缓存的名称,可以通过指定名称获取指定的某个Cache对象
maxElementsInMemory :内存中允许存储的最大的元素个数,0代表无限个
clearOnFlush:内存数量最大时是否清除。
eternal :设置缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。根据存储数据的不同,例如一些静态不变的数据如省市区等可以设置为永不过时
timeToIdleSeconds : 设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds :缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
overflowToDisk :内存不足时,是否启用磁盘缓存。
maxEntriesLocalDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
maxElementsOnDisk:硬盘最大缓存个数。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。