zoukankan      html  css  js  c++  java
  • 【Mybatis】MyBatis之缓存(七)

    MyBatis缓存介绍

    Mybatis 使用到了两种缓存:一级缓存(本地缓存、local cache)和二级缓存(second level cache)。

      一级缓存:基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。

      二级缓存:与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。

      对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

    Mybatis一级缓存

      测试代码如下:

     1     /**
     2      * * 一级缓存:(本地缓存):sqlSession级别的缓存。一级缓存是一直开启的;SqlSession级别的一个Map
     3      *         与数据库同一次会话期间查询到的数据会放在本地缓存中。
     4      *         以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;
     5      * 
     6      *         一级缓存失效情况(没有使用到当前一级缓存的情况,效果就是,还需要再向数据库发出查询):
     7      *         1、sqlSession不同。
     8      *         2、sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)
     9      *         3、sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)
    10      *         4、sqlSession相同,手动清除了一级缓存(缓存清空)
    11      * @throws IOException
    12      */
    13     @Test
    14     public void testFirstLevelCache() throws IOException {
    15         
    16         InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    17         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    18         
    19         SqlSession session = sqlSessionFactory.openSession(true);
    20         
    21         try {
    22             // 一级缓存查询
    23             EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    24             Employee employee = mapper.getEmployeeById(1);
    25             System.out.println(employee);
    26             
    27             Employee employee2 = mapper.getEmployeeById(1);
    28             System.out.println(employee2);
    29             
    30             System.out.println(employee == employee2);
    31             
    32             // 清除缓存
    33             session.clearCache(); 
    34             Employee employee3 = mapper.getEmployeeById(1);
    35             System.out.println(employee3);
    36             
    37             // cud操作
    38             Employee newEmploye = new Employee(1, "大白", "1", "dabai@163.com");
    39             boolean updateEmployee = mapper.updateEmployee(newEmploye);
    40             Employee employee4 = mapper.getEmployeeById(1);
    41             System.out.println(employee4);
    42             System.out.println(employee4 == newEmploye);
    43             
    44         } catch (Exception e) {
    45             e.printStackTrace();
    46         }finally {
    47             session.close();
    48         }
    49     }

      运行代码:

        

        可以看到查询sql只执行了一次,并且employee与employee02是同一个对象

        清除缓存后,重新执行的查询sql

        cud操作后,重新执行的查询sql

    Mybatis二级缓存

      1、相关配置

        a、在mybatis全局配置文件中配置:

    1 <!-- 设置二级缓存,默认是true -->
    2 <setting name="cacheEnabled" value="true"/>

        b、在EmployeeMapper.xml文件中配置

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

      2、测试代码如下:

     1     /**
     2      * * 二级缓存:(全局缓存):基于namespace级别的缓存:一个namespace对应一个二级缓存:
     3      *         工作机制:
     4      *         1、一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
     5      *         2、如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
     6      *         3、sqlSession===EmployeeMapper==>Employee
     7      *                         DepartmentMapper===>Department
     8      *             不同namespace查出的数据会放在自己对应的缓存中(map)
     9      *             效果:数据会从二级缓存中获取
    10      *                 查出的数据都会被默认先放在一级缓存中。
    11      *                 只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中
    12      *         使用:
    13      *             1)、开启全局二级缓存配置:<setting name="cacheEnabled" value="true"/>
    14      *             2)、去mapper.xml中配置使用二级缓存:
    15      *                 <cache></cache>
    16      *             3)、POJO需要实现序列化接口
    17      * 
    18      * 
    19      * @throws IOException
    20      */
    21     @Test
    22     public void testSecondLevelCache() throws IOException {
    23         
    24         InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    25         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    26         
    27         SqlSession sqlSession = sqlSessionFactory.openSession();
    28         SqlSession sqlSession2 = sqlSessionFactory.openSession();
    29         
    30         EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
    31         EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);
    32         
    33         Employee employee01 = mapper.getEmployeeById(1);
    34         System.out.println(employee01);
    35         sqlSession.close();
    36         
    37         Employee employee02 = mapper2.getEmployeeById(1);
    38         System.out.println(employee02);
    39         sqlSession2.close();
    40         
    41     }

      运行代码:

        

        可以看到查询sql只执行了一次,并且employee01与employee02不是同一个对象

    缓存有关的设置/属性

      1)、cacheEnabled=true:false:关闭缓存(二级缓存关闭)(一级缓存一直可用的)
      2)、每个select标签都有useCache="true":
          false:不使用缓存(一级缓存依然使用,二级缓存不使用)
      3)、【每个增删改标签的:flushCache="true":(一级二级都会清除)】
          增删改执行完成后就会清楚缓存;
          测试:flushCache="true":一级缓存就清空了;二级也会被清除;
          查询标签:flushCache="false":
          如果flushCache=true;每次查询之后都会清空缓存;缓存是没有被使用的;
      4)、sqlSession.clearCache();只是清楚当前session的一级缓存;
      5)、localCacheScope:本地缓存作用域:(一级缓存SESSION);当前会话的所有数据保存在会话缓存中;
         STATEMENT:可以禁用一级缓存;

    第三方缓存整合-ehcache

      本例整合第三方缓存ehcache,文档参考:http://www.mybatis.org/ehcache-cache/

      1、ehcache相关jar包 

     1 <!-- mybatis与ehcache缓存适配包 -->
     2 <dependency>
     3     <groupId>org.mybatis.caches</groupId>
     4     <artifactId>mybatis-ehcache</artifactId>
     5     <version>1.1.0</version>
     6 </dependency>
     7 
     8 <!-- ehcache缓存核心jar包 -->
     9 <dependency>
    10     <groupId>net.sf.ehcache</groupId>
    11     <artifactId>ehcache-core</artifactId>
    12     <version>2.6.11</version>
    13 </dependency>

      2、添加ehcache的配置文件ehcache.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3  xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
     4     <!-- 磁盘保存路径 -->
     5     <diskStore path="/Users/h__d/Documents/log/ehcache" />
     6     
     7     <defaultCache 
     8       maxElementsInMemory="10000" 
     9       maxElementsOnDisk="10000000"
    10       eternal="false" 
    11       overflowToDisk="true" 
    12       timeToIdleSeconds="120"
    13       timeToLiveSeconds="120" 
    14       diskExpiryThreadIntervalSeconds="120"
    15       memoryStoreEvictionPolicy="LRU">
    16     </defaultCache>
    17 </ehcache>
    18  
    19 <!-- 
    20 属性说明:
    21 l diskStore:指定数据在磁盘中的存储位置。
    22 l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
    23  
    24 以下属性是必须的:
    25 l maxElementsInMemory - 在内存中缓存的element的最大数目 
    26 l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
    27 l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
    28 l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
    29  
    30 以下属性是可选的:
    31 l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
    32 l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
    33  diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
    34 l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
    35 l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
    36 l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
    37  -->

      3、在EmployeeMapper.xml文件中配置

    1 <!-- 使用ehcache作为二级缓存 -->    
    2 <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

      此时运行上例中测试二级缓存方法,testSecondLevelCache,即可看到使用了ehcache。

  • 相关阅读:
    Atitit 图像金字塔原理与概率 attilax的理解总结qb23
    Atitit.软件中见算法 程序设计五大种类算法
    百度之星
    linux下编程IDE环境
    c++多态的实现 VC++消息映射的实现
    static_cast, const_cast,dynamic_cast和reinterpret_cast
    X Window研究笔记(1)~22
    关于串口发送短信
    模式识别中的核方法
    IC设计,verilog学习链接
  • 原文地址:https://www.cnblogs.com/h--d/p/10889760.html
Copyright © 2011-2022 走看看