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></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(先进先出)
 -->
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值