mybatis高級知之查詢緩存

1.查詢緩存

1.1什麼是查詢緩存

mybatis提供查詢緩存,用於減輕數據壓力,提升數據庫性能
mybatis提供一級緩存二級緩存


一級緩存是SQLSession級別的緩存
    在操做數據庫時須要構造SQLSession對象,在對象中有一個數據結構(HashMap)用戶存儲緩存數據
不一樣的SQLSession之間的緩存數據的區域(HashMap)是互不影響的。

二級緩存是mapper級別的緩存
    多個SQLSession去操做同一個Mapper的sql語句,多個SqlSession能夠共用二級緩存,二級緩存是SQLSession的

爲何要存儲?
    若是緩存中有數據就不用在從數據庫中獲取,大大提升系統的性能。
1234567891011121314複製代碼

2一級緩存

2.1一級緩存的工做原理
        第一次發起查詢用戶id爲1的用戶的信息,先去找緩存中是否有id爲1的用戶信息,若是沒有,從數據庫查詢用戶
        信息
        獲得用戶信息,將用戶信息存儲到一級存儲中

        若是在SQLSession去執行commit操做(執行插入,更新,刪除)清空SQLSession中的一級緩存。這樣作的目的
        爲了緩存中永遠存儲的是最新的信息,避免髒讀       
        第二次發起查詢用戶id爲1的用戶信息,先去查詢緩存中是否有id爲1的用戶信息,緩存中有,直接從緩存中獲取
        用戶信息
    2.2一級緩存測試
        mybatis默認支持一級緩存,不須要在配置文件去配置
        按照上邊一級緩存原理步驟測試
12345678910111213複製代碼
測試代碼
            public testCacher1() throws Exception{
            SqlSession sqlSesssion=sqlSessionFactory.openSession();//建立代理對象
            UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
                //下邊查詢使用一個SqlSession
                //第一次發起請求,查詢id爲1的用戶
                User uyser=userMapper.findUserById(1);
                System.out.println(:user1);
                //若是SQLSession去執行commit操做(執行插入,更新,刪除) 清空SQLSession中的一級緩存
                這樣作的目的是爲了讓緩存中存儲的是最新的信息,避main髒讀
                //更新user的信息
                user.setUsername(「測試用戶22」);
                userMapper.updateUser(user1);
                //執行commint操做去清除緩存
                SQLSession.commit();
                //第二次發起請求,查詢id爲1的用戶
                User user2=username.fiondUserById(1);
                System.out.println(user2);
                sqlSession.close();

            }123456789101112131415161718192021複製代碼
2.3一級緩存的應用
    正式開發,是將mybatis和spring進行整合開發,事務空載子service中
    一個service方法中包括不少mapper方法調用
    service
        //開始執行執行時,開啓事務,建立SQLSession對象
        //第一調用mapper的方法findUserByID(1);
        //第二次調用mapper的方法findUserByID(1);從一級緩存中取數據
        //方法結束sqlSession關閉
    若是是倆次service調用查詢相同的用戶信息,不走一級緩存,由於service方法結束,SQLSession就關閉
    一級緩存就清空。    
1234567891011複製代碼

3.二級緩存

首先開啓mybatis的二級緩存
    SQLSession去查詢用戶id爲1的用戶信息,查詢到用戶信息會將查詢數據存儲到二級緩存中
    若是SQLSession去執行相同mapper下sql,執行commit提交,清空該mapper下的二級緩存區域的數據
    SQLSession去查詢用戶id爲1的用戶信息,去緩存中查中是否存在數據,若是存在直接從緩存中取出數據
    二級緩存與一級緩存區別:二級緩存的範圍更大,多個SQLSession能夠共享一個UserMapper二級緩存
    UserMapper有一個二級緩存區域(按照namespace分),其餘的mapper也有本身的緩存區域(按照namespace分)
    每個namespace的mapper有一個二級緩存區域,若是倆個mapper的namespace若是相同,這倆個
    mapper執行sql查詢到的數據就存在相同的二級緩存區域中
3.1開啓二級緩存
12345678910複製代碼
mybatis的二級緩存是mapper範圍級別,除了在SqlMapConfig.xml設置二級緩存的總開關,還要在具體的mapper.xml
        中開啓二級緩存
        二級緩存使用,須要在主文件中進行配置:
            ①啓用二級緩存
            <!-- 啓用二級緩存 -->
            <setting name="cacheEnabled" value="true"/>

    在UserMapper中開啓二級緩存,UserMapper.xml下的sql執行完成會存儲到它的緩存區域(HashMap)、
    <mapper namespace="mybaties.mapper.User,apper">
    <!--開啓本mapper的namespace下的二級緩存-->
    <cache/>1234567891011複製代碼
3.2調用pojo類實現序列化接口
12複製代碼
public class User implements Serializables{
        private int id;
        private String username;
        private String sex;
        private Date birthday;
        private String address;
    }1234567複製代碼
爲了將緩存的數據取出執行序列化操做,由於二級緩存的存儲介質多種多樣,不必定在內存

3.3測試方法
1234複製代碼
public testCacher2() throws Exception{
            SqlSession sqlSesssion=sqlSessionFactory.openSession();
            SqlSession sqlSesssion2=sqlSessionFactory.openSession();
            SqlSession sqlSesssion3=sqlSessionFactory.openSession();

            //建立代理對象
            UserMapper userMapper=sqlSession.getMapper(UserMapper.class);

                //下邊查詢使用一個SqlSession
                //第一次發起請求,查詢id爲1的用戶
                User uyser=userMapper.findUserById(1);
                System.out.println(:user1);
                //這裏執行關閉操做,將SQLSession中的數據寫到二級緩存區域
                SQLSession.close();             

                //使用SQLSession執行commit()操做
                UserMapper userMapper3=sqlSession3.getMapper(UserMapper.class);
                User user=userMapper3.findUserById(1);
                user.setUsername(「測試用戶22」);
                userMapper3.updateUser(user1);
                //執行commint操做去清除緩存
                SQLSession3.commit();
                SQLSession3.close();

                UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
                //第二次發起請求,查詢id爲1的用戶
                User user2=userMapper2.findUserById(1);
                Stystem.out.println(user2);
                sqlSession2.close();


            }
123456789101112131415161718192021222324252627282930313233複製代碼
3.4useCache配置
    ①.設置useCache=false能夠禁用當前select語句的二級緩存,即每次查詢都會發出sql去查詢,默認狀況是true,即該sql使用二級緩存。
    <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
    總結:針對每次查詢都須要最新的數據sql,要設置成useCache=false,禁用二級緩存。
    ②.清空緩存
    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true"> 
    總結:通常下執行完commit操做都須要刷新緩存,flushCache=true表示刷新緩存,這樣能夠避免數據庫髒讀。
    注意:

    (1)當爲select語句時:

    flushCache默認爲false,表示任什麼時候候語句被調用,都不會去清空本地緩存和二級緩存。

    useCache默認爲true,表示會將本條語句的結果進行二級緩存。

    (2)當爲insert、update、delete語句時:

    flushCache默認爲true,表示任什麼時候候語句被調用,都會致使本地緩存和二級緩存被清空。

    useCache屬性在該狀況下沒有。

    當爲select語句的時候,若是沒有去配置flushCache、useCache,那麼默認是啓用緩存的,因此,若是有必要,那麼就須要人工修改配置

    4.mybatis整合ehcache
        4.1分佈式緩存
        咱們系統爲了提升系統併發,性能。通常對系統進行分佈式部署。(集羣部署方式)
        不使用分佈緩衝池緩存的數據在各自服務器單獨存儲,不方便系統開發,因此要對分佈式緩存對緩存數據進行集中管理
        mybatis沒法實現分佈式緩存。須要和其餘分佈式緩存框架進行整合
        4.2整合的方法
        mybatis提供了一個cache接口,若是要實現本身的存儲邏輯,實現cache接口開發便可
        mybatis和ehcache整合,mybatis和ehcache集合包中提供了一個cache接口的實現類
1234567891011121314151617181920212223242526272829303132複製代碼
public interface Cache{
                String getId();
                void putObject(Object key ,Object value);
                Object getObject(Object key);


            }
        mybatis默認實現的cache類是
        public class PerpetualCache implements Cache{
            private String id;
            private Map<Object,Object> cache=new HashMap<Object,Object>();
            public PerpetualCache(String id){
                this.id=id;

            }
            public String getId(){
                return id;
            }
        }

123456789101112131415161718192021複製代碼
4.3配置信息
12複製代碼
配置mapper中的cache中的type爲ehcache對cache接口的實現
    <mapper namespace="mybatis.mapper.UserMapper">
        <!-- 開啓mapper的namespace下的二級緩存
            type:指定Cache接口的實現類的類型,mybatis默認使用PerpetualCache
            要和ehcache整合:須要配置type爲ehcache實現cache接口類型
            -->
        <caahe type="org.mybatis.caches.ehcache.EhcacheCache"/>1234567複製代碼
3.4加入ehcache包
    ehcache-core-2.6.5.jar
    mybatis-ehcache-1.0.2jar

    3.5加入ehcache的配置文件
123456複製代碼
在classpath下配置
             1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             2 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
             3 <diskStore path="F:\develop\ehcache" />
             4 <defaultCache
             5 maxElementsInMemory="1000"
             6 maxElementsOnDisk="10000000"
             7 eternal="false"
             8 overflowToDisk="false"
             9 timeToIdleSeconds="120"
            10 timeToLiveSeconds="120"
            11 diskExpiryThreadIntervalSeconds="120"
            12 memoryStoreEvictionPolicy="LRU">
            13 </defaultCache>
            14 </ehcache> 123456789101112131415複製代碼
屬性說明:
             diskStore:指定數據在磁盤中的存儲位置。
             defaultCache:當藉助CacheManager.add("demoCache")建立Cache時,EhCache便會採用<defalutCache/>指定的的管理策略
            如下屬性是必須的:
             maxElementsInMemory - 在內存中緩存的element的最大數目 
             maxElementsOnDisk - 在磁盤上緩存的element的最大數目,如果0表示無窮大
             eternal - 設定緩存的elements是否永遠不過時。若是爲true,則緩存的數據始終有效,若是爲false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷
             overflowToDisk - 設定當內存緩存溢出的時候是否將過時的element緩存到磁盤上
            如下屬性是可選的:
             timeToIdleSeconds - 當緩存在EhCache中的數據先後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,這些數據便會刪除,默認值是0,也就是可閒置時間無窮大
             timeToLiveSeconds - 緩存element的有效生命期,默認是0.,也就是element存活時間無窮大
            diskSpoolBufferSizeMB 這個參數設置DiskStore(磁盤緩存)的緩存區大小.默認是30MB.每一個Cache都應該有本身的一個緩衝區.
             diskPersistent - 在VM重啓的時候是否啓用磁盤保存EhCache中的數據,默認是false。
             diskExpiryThreadIntervalSeconds - 磁盤緩存的清理線程運行間隔,默認是120秒。每一個120s,相應的線程會進行一次EhCache中數據的清理工做
             memoryStoreEvictionPolicy - 當內存緩存達到最大,有新的element加入的時候, 移除緩存中element的策略。默認是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出
    4二級緩存應用場景
        應用場景:
123456789101112131415161718複製代碼

   對於訪問多的查詢請求且用戶對查詢結果實時性要求不高,此時可採用mybatis二級緩存技術下降數據庫訪問量,提升訪
問速度,業務場景好比:耗時較高的統計分析sql、電話帳單查詢sql等。實現方法以下:經過設置刷新間隔時間,由mybatis每隔一段時
間自動清空緩存,根據數據變化頻率設置緩存刷新間隔flushInterval,好比設置爲30分鐘、60分鐘、24小時等,根據需求而定。spring

5.侷限性:
  mybatis二級緩存對細粒度的數據級別的緩存實現很差,好比以下需求:對商品信息進行緩存,因爲商品信息查詢訪問量大,
可是要求用戶每次都能查詢最新的商品信息,此時若是使用mybatis的二級緩存就沒法實現當一個商品變化時只刷新該商品的緩
存信息而不刷新其它商品的信息,由於mybaits的二級緩存區域以mapper爲單位劃分,當一個商品信息變化會將全部商品信息
的緩存數據所有清空。解決此類問題須要在業務層根據需求對數據有針對性緩存。複製代碼
相關文章
相關標籤/搜索