本地缓存,sqlSession级别的缓存,一级缓存是一直开启的。本质是SqlSession级别的一个Map。
与数据库同一次会话期间查询到的数据会存放在本地缓存中。
以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。
一级缓存失效情况(没有使用到当前一级缓存的情况,效果是,还需要向数据库发出查询)
.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>
(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.ehcachegroupId>
<artifactId>ehcache-coreartifactId>
<version>2.6.11version>
dependency>
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.1.0version>
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
<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>