1. 程式人生 > >Spring+SpringMVC+MyBatis深入學習及搭建(八)——MyBatis查詢快取

Spring+SpringMVC+MyBatis深入學習及搭建(八)——MyBatis查詢快取

1.什麼是查詢快取

mybatis提供查詢快取,用於減輕資料庫壓力,提高資料庫效能。

mybatis提供一級快取和二級快取。

一級快取是SqlSession級別的快取。在操作資料庫時需要構造sqlSession物件,在物件中有一個數據結構(HashMap)用於儲存快取資料。不同的sqlSession之間的快取資料區域(HashMap)是互相不影響的。

二級快取是mapper級別的快取,多個sqlSession去操作同一個Mapper的sql語句,多個sqlSession可以共用二級快取,二級快取是跨sqlSession的。

為什麼要用快取?

如果快取中有資料就不用從資料庫中獲取,大大提高系統性能。

2.一級快取

2.1一級快取工作原理

 第一次發起查詢使用者id為1的使用者資訊,先去找快取中是否有id為1的使用者資訊,如果沒有,從資料庫查詢使用者資訊。

得到使用者資訊,將使用者資訊儲存到一級快取中。

如果sqlSession去執行commit操作(執行插入、更新、刪除),清空sqlSession中的一級快取,這樣做的目的為了讓快取中儲存的是最新的資訊,避免髒讀。

第二次發去查詢使用者id為1的使用者資訊,先去找快取中是否有id為1的使用者資訊,快取中有,直接從快取中獲取使用者資訊。

 2.2一級快取測試

 mybatis預設支援一級快取,不需要在配置檔案去配置。

 按照上邊一級快取原理步驟去測試。

    @Test
    public void testCache1() throws Exception{
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        //下邊查詢使用一個SqlSession
        //第一次發起請求,查詢id為1的使用者
        User user1=userMapper.findUserById(1);
        System.out.println(user1);
        
        
//如果sqlSession去執行commit操作(執行插入、更新、刪除),清空sqlSession中的一級快取, //這樣做的目的是為了讓快取中儲存的是最新的資訊,避免髒讀。 //更新user1的資訊 user1.setUsername("測試使用者22"); userMapper.updateUser(user1); //執行commit操作去清空快取 sqlSession.commit(); //第二次發起請求,查詢id為1的使用者 User user2=userMapper.findUserById(1); System.out.println(user2); sqlSession.close(); }

2.3一級快取應用

 正式開發,是將mybatis和spring進行整合開發,事務控制在service中。

一個service方法中包括很多Mapper方法呼叫。

service{

  //開始執行時,開啟事務,建立SqlSession物件

  //第一次呼叫mapper的方法findUserById(1)

  //第二次呼叫mapper的方法findUserById(1),從一級快取中取資料

  //方法結束,sqlSession關閉

}

如果是執行兩次service呼叫查詢相同的使用者資訊,不走一級快取,因為session方法結束,sqlSession就關閉,一級快取就清空。

3.二級快取

3.1二級快取原理

首先開啟mybatis的二級快取。

sqlSession1去查詢使用者id為1的使用者資訊,查詢到使用者資訊後悔講查詢資料儲存到二級快取中。

如果sqlSession3去執行相同mapper下的sql,執行commit提交,會清空該mapper下的二級快取區域的資料。

sqlSession2去查詢使用者id為1的使用者資訊,去快取中找是否存在資料,如果存在直接從快取中取出資料。

二級快取與一級快取區別:二級快取的範圍更大,多個sqlSession可以共享一個UserMapper的二級快取區域。UserMapper有一個二級快取區域(按namespace分),其它mapper也有自己的二級快取區域(按namespace分)。

每個namespace的mapper都有一個二級快取區域,兩個mapper的namespace如果相同,這兩個mapper執行sql查詢到的資料將存在相同的二級快取區域中。

3.2開啟二級快取

mybatis的二級快取是mapper範圍級別,除了在SqlMapConfig.xml設定二級快取的總開關,還要在具體的mapper.xml中開啟二級快取。

在核心配置檔案SqlMapConfig.xml中加入:

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

描述

允許值

預設值

cacheEnabled

對在此配置檔案下的所有cache 進行全域性性開/關設定。

true false

true

在UserMapper.xml中開啟二級快取,UserMapper.xml下的sql執行完成後儲存在它的快取區域(HashMap)。

3.3呼叫pojo類實現序列化介面

為了將快取資料取出執行反序列劃操作,因為二級快取資料儲存介質多種多樣,不一定在記憶體。可能在硬碟、遠端等。

3.4測試方法

    @Test
    public void testCache2() throws Exception{
        SqlSession sqlSession1=sqlSessionFactory.openSession();
        SqlSession sqlSession2=sqlSessionFactory.openSession();
        SqlSession sqlSession3=sqlSessionFactory.openSession();
        
        UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
        UserMapper userMapper3=sqlSession3.getMapper(UserMapper.class);
        
        //第一次發起請求,查詢id為1的使用者
        User user1=userMapper1.findUserById(1);
        System.out.println(user1);
        //這裡執行關閉操作,將sqlSession中的資料寫到二級快取區域
        sqlSession1.close();
        
        //使用sqlSession3執行commit()操作
        User user=userMapper3.findUserById(1);
        user.setUsername("Joanna");
        userMapper3.updateUser(user);
        //執行提交,清空UserMapper下邊的二級快取
        sqlSession3.commit();
        sqlSession3.close();
        
        //第二次發起請求,查詢id為1的使用者
        User user2=userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }

3.5禁用二級快取

在statement中設定useCache=false可以禁用當前select語句的二級快取,即每次查詢都會發出sql,預設情況是true,即該sql使用二級快取。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

3.6重新整理快取(就是清空快取)

 在mapper的同一個namespace中,如果有其它insert、update、delete操作資料後需要重新整理快取,如果不執行重新整理快取會出現髒讀。

設定statement配置中的flushCache="true"屬性,預設情況下為true即重新整理快取,如果改成false則不會重新整理。使用快取時如果手動修改資料庫表中的查詢資料會出現髒讀。

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

 總結:一般情況下執行完commit操作都需要重新整理快取,flushCache=true表示重新整理快取,這樣可以避免資料庫髒讀。

3.7 Mybatis Cache引數

flushInterval(重新整理間隔)可以被設定為任意的正整數,而且它們代表一個合理的毫秒形式的時間端。預設情況是不設定,也局勢沒有重新整理間隔,快取僅僅呼叫語句時重新整理。

size(引用數目)可以被設定為任意正整數,要記住你快取的物件數目和你執行環境的可用記憶體資源數目。預設值是1024。

readOnly(只讀)屬性可以被設定為true或false。只讀的快取會給所有呼叫者返回快取物件的相同例項。因此這些物件不能被修改。這提供了很重要的效能優勢。可讀寫的快取會返回快取物件的拷貝(通過序列化)。這會慢一些,但是安全,因此預設是false。

如下例子:

<cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>

這個更高階的配置建立了一個 FIFO 快取,並每隔 60 秒重新整理,存數結果物件或列表的 512 個引用,而且返回的物件被認為是隻讀的,因此在不同執行緒中的呼叫者之間修改它們會導致衝突。可用的收回策略有, 預設的是 LRU:

  1. LRU – 最近最少使用的:移除最長時間不被使用的物件。
  2. FIFO – 先進先出:按物件進入快取的順序來移除它們。
  3. SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。
  4. WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。

4.mybatis整合ehcache

ehcache是一個純Java的程序內快取框架,是一種廣泛使用的開源Java分散式快取,具有快速、精幹等特點,是Hibernate中預設的CacheProvider。

4.1分散式快取

為了提高系統併發、效能,一般會系統進行分散式部署(叢集部署方式)

不使用分散式快取,快取的資料在各個服務單獨儲存,不方便系統開發。所以要使用分散式快取對快取資料進行集中管理。

mybatis的特長是sql操作,快取資料的管理不是mybatis的特長。mybatis無法實現分散式快取,需要和其它分散式快取框架進行整合,如:redis、memcached、ehcache等。

4.2整合方法(掌握)

mybatis提供了一個cache介面,如果要實現自己的快取邏輯,實現cache介面開發即可。

mybatis和ehcache整合,mybatis和ehcache整合包中提供了一個cache介面的實現類。

mybatis預設的cache實現類是:

4.3加入ehcache包

4.4整合ehcache

配置mapper中cache中的type為ehcache對cache介面的實現型別。

4.5加入ehcache的配置檔案

在classpath下配置ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <diskStore path="F:\develop\ehcache" />
    <defaultCache 
        maxElementsInMemory="1000" 
        maxElementsOnDisk="10000000"
        eternal="false" 
        overflowToDisk="false" 
        timeToIdleSeconds="120"
        timeToLiveSeconds="120" 
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

屬性說明:

diskStore:指定資料在磁碟中的儲存位置。

defaultCache:當藉助CacheManager.add(“demoCache”)建立Cache時,EhCache便會採用<defaultCache/>指定的管理策略。

以下屬性是必須的:

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.6測試程式

同3.4

4.7二級快取應用場景

 對訪問多的查詢請求且使用者對查詢結果實時性要求不高,此時可採用mybatis二級快取技術降低資料庫訪問量,提高訪問速度,業務場景比如:耗時較高的統計分析sql、電話賬單查詢sql等。

實現方法如下:通過設定重新整理間隔時間,由mybatis每隔一段時間自動清空快取,根據資料變化頻率設定快取重新整理間隔flushInterval,比如設定為30分鐘、60分鐘、24小時等,根據需求而定。

4.8二級快取侷限性

 mybatis二級快取對細粒度的資料級別的快取實現不好,比如如下需求:對商品資訊進行快取,由於商品資訊查詢訪問量大,但是要求使用者每次都能查詢最新的商品資訊,此時如果使用mybatis的二級快取就無法實現當一個商品變化時只重新整理該商品的快取資訊而不重新整理其它商品的資訊,因為mybatis的二級快取區域以mapper為單位劃分,當一個商品資訊變化會將所有商品資訊的快取資料全部清空。解決此類問題需要再業務層根據需求對資料有針對性快取。

如果此文對您有幫助,微信打賞我一下吧~ 

 

相關推薦

Spring+SpringMVC+MyBatis深入學習搭建()——MyBatis查詢緩存

idt rtu void spring 寫到 查詢緩存 修改 針對 target 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6956206.html 前面講到:Spring+SpringMVC+MyBatis深入學習及搭建(

Spring+SpringMVC+MyBatis深入學習搭建()——MyBatis查詢快取

1.什麼是查詢快取 mybatis提供查詢快取,用於減輕資料庫壓力,提高資料庫效能。 mybatis提供一級快取和二級快取。 一級快取是SqlSession級別的快取。在操作資料庫時需要構造sqlSession物件,在物件中有一個數據結構(HashMap)用於儲存快取資料。不同的sqlSession之間

Spring+SpringMVC+MyBatis深入學習搭建(三)——MyBatis全局配置文件解析

保持 nbsp 延遲加載 行為 span 方便 doc ima actor 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6874672.html 前面有寫到Spring+SpringMVC+MyBatis深入學習及搭建(二)&

Spring+SpringMVC+MyBatis深入學習搭建(四)——MyBatis輸入映射與輸出映射

指定 2.6 face 生成 shm hashmap ace and 包裝 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6878529.html 前面有講到Spring+SpringMVC+MyBatis深入學習及搭建(三)&

Spring+SpringMVC+MyBatis深入學習搭建(十)——MyBatis逆向工程

cat springmvc blank 不為 tex llc root from ssi 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6973266.html 前面講到:Spring+SpringMVC+MyBatis深入學習及

Spring+SpringMVC+MyBatis深入學習搭建(二)——MyBatis原始Dao開發和mapper代理開發

oid 方法註入 內部 需要 com 配置文件信息 lec lang auth 前面有寫到Spring+SpringMVC+MyBatis深入學習及搭建(一)——MyBatis的基礎知識。MybatisFirst中存在大量重復的代碼。這次簡化下代碼: 使用MyBatis開發

Spring+SpringMVC+MyBatis深入學習搭建(四)——MyBatis輸入映射與輸出映射(轉發同上)

resultmap 根據 except 就會 ash 用戶名 mvc html like 原地址:http://www.cnblogs.com/shanheyongmu/p/7121556.html 1. 輸入映射 通過parameterType指定輸入參數的類型,類型可

Spring+SpringMVC+MyBatis深入學習搭建(九)——MyBatisSpring整合

1.整合思路需要Spring通過單例方式管理SqlSessionFactory。Spring和MyBatis整合生成代理物件,使用SqlSessionFactory建立SqlSession。(Spring和MyBatis整合自動完成)持久層的mapper都需要由Spring進

Spring+SpringMVC+MyBatis深入學習搭建(七)——MyBatis延遲載入

1.什麼是延遲載入 resultMap可以實現高階對映(使用association、collection實現一對一及一對多對映),association、collection具備延遲載入功能。 需求: 如果查詢訂單並且關聯查詢使用者資訊。如果先查詢訂單資訊即可滿足要求,當我們需要查詢使用者資訊時再查下使用

Spring+SpringMVC+MyBatis深入學習搭建(六)——MyBatis關聯查詢

1.商品訂單資料模型 1.1資料模型分析思路 (1)每張表記錄的資料內容   分模組對每張表記錄的內容進行熟悉,相當於你學習系統需求(功能)的過程。 (2)每張表重要的欄位設定   非空欄位、外來鍵欄位 (3)資料庫級別表與表之間的關係   外來鍵關係 (4)表與表之間的業務關係   在分析表與表之間的

Spring+SpringMVC+MyBatis深入學習搭建(四)——MyBatis輸入對映與輸出對映

1. 輸入對映 通過parameterType指定輸入引數的型別,型別可以是簡單型別、hashmap、pojo的包裝型別。 1.1 #{}與${} #{}實現的是向prepareStatement中的預處理語句設定引數值,sql語句中#{}表示一個佔位符即? <select id="findUse

Spring+SpringMVC+MyBatis深入學習搭建(三)——MyBatis全域性配置檔案解析

MyBatis的全域性配置檔案SqlMapConfig.xml,配置內容和順序如下: properties(屬性) setting(全域性配置引數) typeAliases(類名別名) typeHandlers(類名處理器) objectFactory(物件工廠) plugins(外掛) environm

Spring+SpringMVC+MyBatis深入學習搭建(十一)——SpringMVC架構

框架 ppi spring框架 edit 不同的 com get request html 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6985816.html 前面講到:Spring+SpringMVC+MyBatis深入學習

Spring+SpringMVC+MyBatis深入學習搭建(十四)——SpringMVCMyBatis整合

文件拷貝 conf lips glib ide doc from ive body 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/7010363.html 前面講到:Spring+SpringMVC+MyBatis深入學習及搭建(

Spring+SpringMVC+MyBatis深入學習搭建(五)——動態sql

mybatis核心:對sql語句進行靈活操作,通過表示式進行判斷,對sql進行靈活拼接、組裝。 mybatis提供各種標籤方法實現動態拼接sql。 1. if&where 1.2 需求 使用者資訊綜合查詢列表和使用者資訊查詢列表總數這兩個statement的定義使用動態sql。 對查詢條件進行判斷

Spring+SpringMVC+MyBatis深入學習搭建】17.SpringMVC攔截器

1.攔截器定義 Spring Web MVC的處理器攔截器類似於Servlet開發中的過濾器Filter,用於對處理器進行預處理和後處理。 定義攔截器,實現HandlerInterceptor介面。介面中提供三個方法。 package joanna.yan.ssm.interceptor; imp

spring深入學習(十) IOC 之開啟 bean 的例項化程序

在上篇部落格【死磕 Spring】—– 載入 bean 之 分析各 scope 的 bean 建立中有一個核心方法沒有講到 createBean(),該方法的如下: protected abstract Object createBean(String beanName, RootBe

多執行緒深入學習面試解決思路

課程目標 執行緒與程序區別 為什麼要使用多執行緒? 多執行緒應用場景? 多執行緒建立方式 獲取執行緒物件以及名稱 守護執行緒 多執行緒執行狀態 join()方法作用 多執行緒分批處理資料 作業題 面試題 備註單詞 執行緒與程序區別

Dubbo服務治理框架深入學習面試題

  Dubbo概述 Dubbo的背景 隨著網際網路的發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對,分散式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。  單一應用架構 當網站流量很小時,只需

Mybatis總結(2)-Mybatis的原理搭建

在Mybatis搭建前,應該先了解其執行基本原理 1. 讀取Mybatis的配置檔案-Mybatis-config.xml 2. 由配置檔案的mapper來載入對映檔案mapper.xml 3. 構造一個SqlSessionFactory工廠 4. 用工廠來例項化一個SqlSess