MyBatis学习笔记——缓存

一级缓存

本地缓存,sqlSession级别的缓存,一级缓存是一直开启的。本质是SqlSession级别的一个Map。
与数据库同一次会话期间查询到的数据会存放在本地缓存中。
以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。
一级缓存失效情况(没有使用到当前一级缓存的情况,效果是,还需要向数据库发出查询)

  1. sqlSession不同
  2. sqlSession相同,查询条件不同(一级缓存中还没有这个数据)
  3. sqlSession相同,两次查询期间执行了增删改操作(这次增删改可能对当前缓存数据有影响)
  4. 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>
    

(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:可以禁用一级缓存(少用)。

小结

MyBatis学习笔记——缓存_第1张图片

整合第三方缓存

(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>

你可能感兴趣的:(Mybatis)