MyBatis学习笔记——缓存
一级缓存
本地缓存,sqlSession级别的缓存,一级缓存是一直开启的。本质是SqlSession级别的一个Map。
与数据库同一次会话期间查询到的数据会存放在本地缓存中。
以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。
一级缓存失效情况(没有使用到当前一级缓存的情况,效果是,还需要向数据库发出查询)
- sqlSession不同
- sqlSession相同,查询条件不同(一级缓存中还没有这个数据)
- sqlSession相同,两次查询期间执行了增删改操作(这次增删改可能对当前缓存数据有影响)
- sqlSession相同,手动清除了一级缓存(缓存清空),
.clearCache()
测试
@Test
public void testFirstChace() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee emp01=mapper.getEmpById(1);
System.out.println(emp01);
Employee emp02=mapper.getEmpById(1);
System.out.println(emp02);
System.out.println(emp01==emp02);
} finally {
openSession.close();
}
}
上述代码,只会发出一次查询语句,且打印true
,两个对象是同一个引用。
二级缓存
全局缓存,基于namespace级别的缓存,一个namespace对应一个二级缓存:
工作机制:
(1)一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
(2)如果会话关闭,一级缓存中的数据会被保存到二级缓存中,新的会话查询信息,就可以先查询二级缓存中的内容。
(3)EmployeeMapper<===>employee,而DepartmentMapper<===>department,因为二级缓存是基于Mapper中的namespace的。不同的namespace查出的数据会存放在自己对应的缓存中(map)。
使用步骤:
(1)开启全局二级缓存配置
在全局配置文件中,增加如下配置
<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
(2)去每个Mapper.xml中配置使用二级缓存。
在Mapper XML中加入<cache>
标签即可,它也有一些属性可以配置,具体如下:
<cache></cache>
<!--
eviction:缓存回收策略,默认是LRU.
LRU:最近最少使用,移除最长时间不被使用的对象.
FIFO:先进先出,按对象进入缓存的顺序来移除它们.
SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象.
WEAK:弱引用,更积极地移除基于垃圾回收器状态和弱引用规则的对象.
flushInterval:缓存刷新间隔
缓存多长时间清空一次,默认不清空,设置一个毫秒值
readOnly:是否只读,默认是false
true:只读,MyBatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据.
MyBatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户,不安全,但速度快.
false:非只读,MyBatis觉得获取的数据可能会被修改
使用序列化&反序列化技术克隆一个一份新的数据,安全,速度慢.
size:缓存中放多少元素.
type:指定自定义缓存的全类名,实现org.apache.ibatis.cache.Cache接口即可.
-->
(3)我们的POJO需要实现序列化接口implements Serializable
。
测试
@Test
public void testSecondCache() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
SqlSession openSession2 = sqlSessionFactory.openSession();
try {
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);
openSession.close();
//第二次查询是从二级缓存中拿到的数据,并没有发送新的sql
Employee emp02 = mapper2.getEmpById(1);
System.out.println(emp02);
openSession2.close();
} finally {
}
}
注意细节
查出的数据都会被默认放在一级缓存中,只有会话提交或者关闭以后,一级缓存中的数据才会被转移到二级缓存中。
设置及属性
(1)全局配置文件中的,cacheEnabled
设置为false,二级缓存是肯定关闭的,一级缓存是关不掉的。
(2)每个select标签中,都有一个属性,useCache="true"
,设置成false
,是不使用二级缓存。
(3)每个增删改
标签中,都有一个属性,flushCache="true"
,增删改执行完成后就会清除缓存(一级二级都会被清空,二级会查但是没命中)(select也有该属性,但是默认为false,若改成true,缓存都无效了)
(4)sqlSession.clearCache(),只是清除当前session的一级缓存,对二级缓存无影响。
(5)localCacheScope,本地缓存作用域(SESSION|STATEMENT),Session:当前会话的所有数据保存在当前会话缓存中;STATEMENT:可以禁用一级缓存(少用)。
小结
整合第三方缓存
(1)下载第三方缓存encache,下载jar包,这里使用Maven管理,pom.xml中加入如下:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
其中,第一个为encache的核心包,第二个为mybatis为我们写好的适配包,可以直接使用。
(2)配置使用encache
1)在Mapper XML中加入:
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
</cache>
其他的Mapper XML的加入:
<cache-ref namespace="com.shen.mybaties.dao.EmployeeMapper"/>
引用缓存,与目标namespace使用相同的缓存类型。
2)在类路径下,加入一个配置文件encache.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="D:\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(先进先出)
-->
上一篇: 读取文件写入kafka