zoukankan      html  css  js  c++  java
  • 23、mybatis学习——mybatis的二级缓存

    MyBatis 一级缓存最大的共享范围就是一个SqlSession内部,那么如果多个 SqlSession 需要共享缓存,则需要开启二级缓存,开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在CachingExecutor 进行二级缓存的查询,具体的工作流程如下所示

     当二级缓存开启后,同一个命名空间(namespace) 所有的操作语句,都影响着一个共同的 cache,也就是二级缓存被多个 SqlSession 共享,是一个全局的变量。当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

    二级缓存开启条件

    二级缓存默认是不开启的,需要手动开启二级缓存,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。开启二级缓存的条件也是比较简单,通过直接在 MyBatis 配置文件中通过

    <settings>
        <setting name = "cacheEnabled" value = "true" />
    </settings>

    来开启二级缓存,③还需要在 Mapper 的xml 配置文件中加入 <cache>标签

    设置 cache 标签的属性

    cache 标签有多个属性

    • eviction: 缓存回收策略,有这几种回收策略
      • LRU - 最近最少回收,移除最长时间不被使用的对象(默认)
      • FIFO - 先进先出,按照缓存进入的顺序来移除它们
      • SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象
      • WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象
    • flushinterval 缓存刷新间隔,缓存多长时间刷新一次,默认不清空,设置一个毫秒值
    • readOnly: 是否只读;true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。读写(默认):MyBatis 觉得数据可能会被修改
    • size : 缓存存放多少个元素
    • type: 指定自定义缓存的全类名(实现Cache 接口即可)
    • blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。

    举例:

    Student.java(实现了序列化接口)

    StudentMapper接口和StudentMapper.xml

     mybatis全局配置文件中开启二级缓存

     在StudentMapper.xml开启二级缓存

    <!-- namespace中开启二级缓存
                eviction:缓存的回收策略(默认是LRU)
                    LRU - 最近最少回收,移除最长时间不被使用的对象
                    FIFO - 先进先出,按照缓存进入的顺序来移除它们
                    SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象
                    WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象 
                flushInterval:缓存刷新间隔,缓存多长时间刷新一次,默认不清空,设置一个毫秒值
                readOnly:是否只读;true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。
                        false 非只读(默认):MyBatis觉得获得的数据可能会被修改;mybatis会利用序列化&反序列化的技术克隆一份新的数据给你;安全,速度稍慢
                size:缓存存放多少个元素
                type: 指定自定义缓存的全类名(实现Cache接口即可)
                blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。
                -->
                
         <cache eviction="LRU" flushInterval="60000" readOnly="false"></cache>

    测试方法

        //测试二级缓存
        @Test
        public void testSecondLevelCache() throws IOException {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //两个会话
            SqlSession sqlSession1 = sqlSessionFactory.openSession();
            SqlSession sqlSession2 = sqlSessionFactory.openSession();
            
            StudentMapper studentMapper1 = sqlSession1.getMapper(StudentMapper.class);
            StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);
            
            //会话1关闭,此时student1从一级缓存转移到二级缓存
            Student student1 = studentMapper1.getStuById(1);
            sqlSession1.close();
            
            //会话2查询id为1的student,二级缓存中有,直接取出   
            Student student2 = studentMapper2.getStuById(1);
            sqlSession2.close();
            
            //student2从二级缓存中取出时,若<cache>中的属性readeronly为true
            //则这个输出true,若为false则这里输出false
            System.out.println(student1==student2);
        }

    测试结果

    此时在StudentMapper.xml中修改配置增加一个useCache="false"(<select>标签中才有的属性)

    则此条查询语句不使用二级缓存;及时全局配置文件和当前namespace配置文件开启了二级缓存

    同样进行测试

    总结:

    和二级缓存有关的设置/属性:
    1、需要使用二级缓存的POJO实现序列化接口Serializable
    2、<setting name="cacheEnabled" value="true"/>
    3、<cache></cache>
    4、<select>标签中的useCache属性
    5、mapper.xml中的每一个增删改标签中的flushCache属性,默认为true;执行了增删改操作(一级和二级缓存都会清空)

  • 相关阅读:
    一个涉及到浮点寄存器的CM
    树和二叉树一篇就搞定!
    串的两种模式匹配方式(BF/KMP算法)
    队列的知识讲解与基本实现(数据结构)
    如何用C++实现栈
    判断List集合为空还是null的正确打开方式
    双链表的基本实现与讲解(C++描述)
    Redis从认识安装到实现增删改查
    如何使用C++实现单链表
    线性表——顺序表的实现与讲解(C++描述)
  • 原文地址:https://www.cnblogs.com/lyh233/p/12364792.html
Copyright © 2011-2022 走看看