1. 程式人生 > 其它 >mybatis學習18:快取

mybatis學習18:快取

mybatis學習18:快取

  • 什麼是快取【Cache】:

    • 存在記憶體中的臨時資料

    • 將使用者經常查詢的資料放在快取中,使用者去查詢資料就不用從磁碟上(關係型資料庫資料檔案)查詢;

    • 從快取中查詢:從而提高查詢效率,解決了高併發的效能問題

    • 三高問題:高併發,高可用,高效能!

       

 

  • 為什麼使用快取:

    • 減少和資料庫的互動次數,減少系統開銷,提高系統效率!

      --所有的查詢 -- 都要連線資料庫  -- 耗資源!

      怎麼優化:
      --1,一次查詢的結果,給它暫存在一個可以直接取到的地方!(記憶體)
      --2,這些暫存在記憶體中的資料,就是快取

      我們再次查詢相同資料的時候:
      --1,直接走快取,就不用走資料庫了!

       

       

  • 什麼樣的資料能使用快取:

    • 經常查詢並且不經常改變的資料!【可以使用快取】

 

  • Mybatis快取:

    • Mybatis包含了一個非常強大的查詢快取特性

    • 它可以非常方便地定製和配置快取,快取可以極大的提升查詢效率;

       

    • Mybatis系統中預設定義了兩級快取:一級快取和二級快取:

      • 預設情況下,只有一級快取開啟SqlSession級別的快取,也稱為本地快取);

      • 二級快取需要手動開啟和配置,他是基於namespace級別的快取;

      • 為了提高擴充套件性,Mybatis定義了快取介面Cache,我們可以通過實現Cache介面來定義二級快取;

 



 

  • 一級快取:

    • 一級快取也叫本地快取:

      • 與資料庫同一次會話期間查詢到的資料會放在本地快取中;

      • 以後如果需要獲取相同的資料,直接從快取中拿,沒必要再去查詢資料庫;

         

    • 測試:重點

      • 1,開啟日誌:

        <settings>
           <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
      • 2,測試在一個Session中查詢2次一樣的記錄!

      • 3,檢視日誌輸出:

         

         

    • 快取失效的情況:

      • 1,查詢不同的東西;

      • 2,增刪改操作,可能會改變原來的資料,所以必定會重新整理快取;

      • 3,查詢不同的Mapper.xml;

      • 4,手動清理快取:sqlSession.clearCache();

         

    • 總結:

      • 一級快取預設是開啟的,只在一次SqlSession中有效,也就是拿到連線到關閉連線這個區間段!

      • 一級快取相當於一個map

 



 

  • 二級快取:

    • 二級快取也叫全域性快取,一級快取的作用域太低了,所以誕生了二級快取;

    • 基於namespace級別的快取,一個名稱空間,對應一個二級快取

    • 工作機制:

      • 一個會話查詢一條資料,這個資料就會被放在當前會話的一級快取中;

      • 如果當前會話關閉了,這個會話對應的一級快取就沒了;但是我們想要的是,會話關閉了,一級快取中的資料被儲存到二級快取中;

      • 二級快取生效前提:一級快取死掉;

      • 新的會話查詢資訊,就可以從二級快取中獲取內容;

      • 不同的mapper查出的資料會放在自己對應的快取(map)中;

         

    • 語法:

      • 要啟用全域性的二級快取,只需要在你的 SQL 對映檔案中新增一行;

        <cache/>

         

    • 使用步驟:

      • 1,開啟全域性快取;

        <!--顯示開啟全域性快取-->
        <settings>
           <setting name="cacheEnabled" value="true"/>
        </settings>
      • 2,mapper.xml中引入快取:

        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper
               PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
               "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.ljxdemo.dao.UserMapper">

        <!--在當前Mapper.xml中使用二級快取:方式1
        使用時:要確認pojo實體類必須實現Serializable介面;序列化
        (public class User implements Serializable)
        -->
           <cache/>
           
           <!--在當前Mapper.xml中使用二級快取:方式2-->
           <cache  eviction="FIFO"
                   flushInterval="60000"
                   size="512"
                   readOnly="true"/>
         
        </mapper>
      • 3,測試:

        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper
               PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
               "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.ljxdemo.dao.UserMapper">

        <!--   在當前Mapper.xml中使用二級快取-->
           <cache  eviction="FIFO"
                   flushInterval="60000"
                   size="512"
                   readOnly="true"/>

           <select id="queryUserById" resultType="user" useCache="true">
              select * from user where id=#{id}
           </select>

        </mapper>
        @Test
           public void queryUserById(){
               SqlSession sqlSession1 = MybatisUtils.getSqlSession();
               SqlSession sqlSession2 = MybatisUtils.getSqlSession();
               UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
               List<User> users1 = mapper1.queryUserById(1);
               for (User user : users1) {
                   System.out.println(user);
              }

               sqlSession1.close();//一次快取崩掉
               System.out.println("=====================");

               UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
               List<User> users2 = mapper2.queryUserById(1);
               for (User user : users2) {
                   System.out.println(user);
              }

               sqlSession2.close();
          }

         

      • 測試結果:

    • 總結:

      • 只要開啟了二級快取,在同一個Mapper下才有效;

      • 所有的資料都會先放在一級快取中;

      • 只有當會話提交或者關閉的時候,才會提交到二級快取中;

 

 



 

  • Mybatis快取原理:

     

 

 



 

 

  • 自定義快取-Ehcache:

    • Ehcache是一種廣泛使用的開源Java分散式快取,主要面向通用快取,Java EE和輕量級容器;

       

    • 要在程式中使用:

      • 1,導包;

        <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
        <dependency>
           <groupId>org.mybatis.caches</groupId>
           <artifactId>mybatis-ehcache</artifactId>
           <version>1.2.1</version>
        </dependency>
      • 2,mapper.xml中去配置自定義cache:

        <!--在當前Mapper.xml中使用二級快取-->
        <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
      • 3,新建ehcache.xml:快取策略配置

        <?xml version="1.0" encoding="UTF-8" ?>
        <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
                updateCheck="false">

           <diskStore path="./tmpdir/Tmp_EhCache"/>

           <defaultCache
                   eternal="false"
                   maxElementsInMemory="10000"
                   overflowToDisk="false"
                   diskPersistent="false"
                   timeToIdleSeconds="1800"
                   timeToLiveSeconds="259200"
                   memoryStoreEvictionPolicy="LRU"/>

           <cache
                   name="cloud_user"
                   eternal="false"
                   maxElementsInMemory="5000"
                   overflowToDisk="false"
                   diskPersistent="false"
                   timeToIdleSeconds="1800"
                   timeToLiveSeconds="1800"
                   memoryStoreEvictionPolicy="LRU"/>

           <!--
               defaultCache:預設快取策略,當ehcache找不到定義的快取時,則使用這個快取策略,只能定義一個
           -->

           <!--
               name:快取名稱
               maxElementsInMemory:快取最大數目
               eternal:物件是否永久有效,一旦設定了,timeout將不起作用
               overflowToDisk:是否儲存到磁碟,當系統宕機時
               timeToIdleSeconds:設定物件在失效前的允許閒置時間,單位:秒
               timeToLiveSeconds:設定物件在失效前的允許存活時間,單位:秒

               memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,預設策略),FIFO(先進先出),LFU(最少訪問次數)

           -->
        </ehcache>
      • 4,測試即可!

         

  • 總結:

    • 對映語句檔案中的所有 select 語句的結果將會被快取;

    • 對映語句檔案中的所有 insert、update 和 delete 語句會重新整理快取;