Mybatis緩存機制

緩存技術(shù)是一種“以空間換時間”的設(shè)計理念衣摩,是利用內(nèi)存空間資源來提高數(shù)據(jù)檢索速度的有效手段之一孕索。Mybatis包含一個非常強大的查詢緩存特性甩牺,可以非常方便地配置和定制嘲碱。MyBatis將數(shù)據(jù)緩存設(shè)計成兩級結(jié)構(gòu),分為一級緩存址否、二級緩存吁峻,如下圖所示:


一級緩存


1. 一級緩存簡介
??一級緩存基于PrepetualCache的HashMap本地緩存,其存儲作用域為Session在张,位于表示一次數(shù)據(jù)庫會話的SqlSession對象之中用含。
??每當我們使用MyBatis開啟一次和數(shù)據(jù)庫的會話,MyBatis會創(chuàng)建出一個SqlSession對象表示一次數(shù)據(jù)庫會話帮匾。在對數(shù)據(jù)庫的一次會話中啄骇,我們有可能會反復地執(zhí)行完全相同的查詢語句,如果不采取一些措施的話瘟斜,每一次查詢都會查詢一次數(shù)據(jù)庫缸夹,而我們在極短的時間內(nèi)做了完全相同的查詢,那么它們的結(jié)果極有可能完全相同螺句,由于查詢一次數(shù)據(jù)庫的代價很大虽惭,這有可能造成很大的資源浪費。
??為了解決這一問題蛇尚,減少資源的浪費芽唇,MyBatis會在表示會話的SqlSession對象中建立一個簡單的緩存,將每次查詢到的結(jié)果結(jié)果緩存起來取劫,當下次查詢的時候匆笤,如果判斷先前有個完全一樣的查詢,會直接從緩存中直接將結(jié)果取出谱邪,返回給用戶炮捧,不需要再進行一次數(shù)據(jù)庫查詢了。
??一級緩存是MyBatis內(nèi)部實現(xiàn)的一個特性惦银,用戶不能配置咆课,默認情況下自動支持的緩存,用戶沒有定制它的權(quán)利(不過這也不是絕對的扯俱,可以通過開發(fā)插件對它進行修改)书蚪。

2. 一級緩存實現(xiàn)
??實際上, MyBatis只是一個MyBatis對外的接口,SqlSession將它的工作交給了Executor執(zhí)行器這個角色來完成蘸吓,負責完成對數(shù)據(jù)庫的各種操作善炫。當創(chuàng)建了一個SqlSession對象時,MyBatis會為這個SqlSession對象創(chuàng)建一個新的Executor執(zhí)行器库继,而緩存信息就被維護在這個Executor執(zhí)行器中箩艺,MyBatis將緩存和對緩存相關(guān)的操作封裝成了Cache接口中。
??Executor接口的實現(xiàn)類BaseExecutor中擁有一個Cache接口的實現(xiàn)類PerpetualCache宪萄,則對于BaseExecutor對象而言艺谆,它將使用PerpetualCache對象維護緩存。
??綜上拜英,SqlSession對象静汤、Executor對象、Cache對象之間的關(guān)系如下圖所示:


3. 一級緩存的生命周期

a. MyBatis在開啟一個數(shù)據(jù)庫會話時,會創(chuàng)建一個新的SqlSession對象虫给,SqlSession對象中會有一個新的Executor對象藤抡,Executor對象中持有一個新的PerpetualCache對象;當會話結(jié)束時抹估,SqlSession對象及其內(nèi)部的Executor對象還有PerpetualCache對象也一并釋放掉缠黍。
b. 如果SqlSession調(diào)用了close()方法,會釋放掉一級緩存PerpetualCache對象药蜻,一級緩存將不可用瓷式;
c. 如果SqlSession調(diào)用了clearCache(),會清空PerpetualCache對象中的數(shù)據(jù)语泽,但是該對象仍可使用贸典;
d. SqlSession中執(zhí)行了任何一個update操作(update()、delete()踱卵、insert()) 廊驼,都會清空PerpetualCache對象的數(shù)據(jù),但是該對象可以繼續(xù)使用颊埃;

4. 一級緩存的性能分析
??Cache最核心的實現(xiàn)其實就是一個Map蔬充,將本次查詢使用的特征值作為key,將查詢結(jié)果作為value存儲到Map中班利。所以MyBatis的一級緩存就是使用了簡單的HashMap饥漫,MyBatis只負責將查詢數(shù)據(jù)庫的結(jié)果存儲到緩存中去, 不會去判斷緩存存放的時間是否過長罗标、是否過期庸队,因此也就沒有對緩存的結(jié)果進行更新這一說了。
??此外闯割,Mybatis并沒有對HashMap的容量和大小進行限制彻消,有可能導致OutOfMemoryError錯誤。但是MyBatis這樣設(shè)計也有它自己的理由:
**a. ** 一般而言SqlSession的生存時間很短宙拉。一般情況下使用一個SqlSession對象執(zhí)行的操作不會太多宾尚,執(zhí)行完就會消亡;
**b. ** 對于某一個SqlSession對象而言谢澈,只要執(zhí)行update操作(update煌贴、insert、delete)锥忿,都會將這個SqlSession對象中對應的一級緩存清空掉牛郑,所以一般情況下不會出現(xiàn)緩存過大,影響JVM內(nèi)存空間的問題敬鬓;
**c. **可以手動地釋放掉SqlSession對象中的緩存淹朋。

二級緩存

1. MyBatis二級緩存的介紹和劃分
??二級緩存和一級緩存的機制相同笙各,默認也是采用PrepetualCache、HashMap存儲础芍,但是二級緩存是Application應用級別的緩存杈抢,它的是生命周期很長,跟Application的聲明周期一樣者甲,也就是說它的作用范圍是整個Application應用春感。但是MyBatis并不是簡單地對整個Application就只有一個Cache緩存對象,它將緩存劃分的更細虏缸,即是Mapper(nameSpace)級別的,即每一個Mapper都可以擁有一個Cache對象嫩实,具體如下:

a.為每一個Mapper分配一個Cache緩存對象(使用<cache>節(jié)點配置)
??MyBatis將Application級別的二級緩存細分到Mapper級別刽辙,即對于每一個Mapper.xml,如果在其中使用了<cache> 節(jié)點甲献,則MyBatis會為這個Mapper創(chuàng)建一個Cache緩存對象宰缤,如下圖所示:

注: 上述的每一個Cache對象,都會有一個自己所屬的namespace命名空間晃洒,并且會將Mapper的 namespace作為它們的ID慨灭。

b.多個Mapper共用一個Cache緩存對象(使用<cache-ref>節(jié)點配置)
??如果你想讓多個Mapper公用一個Cache的話,你可以使用<cache-ref namespace="">節(jié)點球及,來指定你的這個Mapper使用到了哪一個Mapper的Cache緩存氧骤。

在同一個namespace下的mapper文件中,執(zhí)行相同的查詢SQL吃引,第一次會去查詢數(shù)據(jù)庫筹陵,并寫到緩存中;第二次直接從緩存中取镊尺。當執(zhí)行SQL時兩次查詢中間發(fā)生了增刪改操作朦佩,則二級緩存清空。


2. 二級緩存的工作模式
??如上所言庐氮,一個SqlSession對象會使用一個Executor對象來完成會話操作语稠,MyBatis的二級緩存機制的關(guān)鍵就是對這個Executor對象做文章。如果用戶配置了"cacheEnabled=true"弄砍,那么MyBatis在為SqlSession對象創(chuàng)建Executor對象時仙畦,會對Executor對象加上一個裝飾者:CachingExecutor,這時SqlSession使用CachingExecutor對象來完成操作請求输枯。CachingExecutor對于查詢請求议泵,會先判斷該查詢請求在Application級別的二級緩存中是否有緩存結(jié)果,如果有查詢結(jié)果桃熄,則直接返回緩存結(jié)果先口;如果緩存中沒有型奥,再交給真正的Executor對象來完成查詢操作,之后CachingExecutor會將真正Executor返回的查詢結(jié)果放置到緩存中碉京,然后在返回給用戶厢汹。

3. 使用二級緩存,必須要具備的條件
??MyBatis對二級緩存的支持粒度很細谐宙,它會指定某一條查詢語句是否使用二級緩存烫葬。
??雖然在Mapper中配置了<cache>,并且為此Mapper分配了Cache對象,這并不表示我們使用Mapper中定義的查詢語句查到的結(jié)果都會放置到Cache對象之中凡蜻,我們必須指定Mapper中的某條選擇語句是否支持緩存搭综,即如下所示,在<select>節(jié)點中配置useCache="true"划栓,Mapper才會對此Select的查詢支持緩存特性兑巾,否則,不會對此select查詢忠荞,不會經(jīng)過Cache緩存蒋歌。如下所示,select語句配置了useCache="true"委煤,則表明這條select語句的查詢會使用二級緩存堂油。

<select id="selectByMinSalary" resultMap="BaseResultMap" parameterType="java.util.Map" useCache="true">  

總之,要想使某條Select查詢支持二級緩存碧绞,你需要保證:

  1. MyBatis支持二級緩存的總開關(guān):全局配置(mybatis-config.xml)變量參數(shù) cacheEnabled=true府框。
  2. 該select語句所在的Mapper,配置了<cache> 或<cached-ref>節(jié)點头遭,并且有效寓免。


  3. 該select語句的參數(shù) useCache=true。
  4. Pojo類必須實現(xiàn)序列化接口计维。


4. 刷新緩存
??在mapper的同一個namespace中袜香,如果有其他insert、update鲫惶、delete操作數(shù)據(jù)后需要刷新緩存蜈首,如果不執(zhí)行刷新緩存會出現(xiàn)臟讀。
??設(shè)置statement配置中的flushCache="true"屬性欠母,默認情況下為true即刷新緩存欢策,如果改成false則不會刷新緩存。

5. 二級緩存實現(xiàn)的選擇
??MyBatis對二級緩存的設(shè)計非常靈活赏淌,它自己內(nèi)部實現(xiàn)了一系列的Cache緩存實現(xiàn)類踩寇,并提供了各種緩存刷新策略如LRU,F(xiàn)IFO等等六水;另外俺孙,MyBatis還允許用戶自定義Cache接口實現(xiàn)辣卒,用戶是需要實現(xiàn)org.apache.ibatis.cache.Cache接口,然后將Cache實現(xiàn)類配置在<cache type="">節(jié)點的type屬性上即可睛榄;除此之外荣茫,MyBatis還支持跟第三方內(nèi)存緩存庫如Ehcache的集成。

MyBatis自身提供的二級緩存的實現(xiàn)
??MyBatis自身提供了豐富的场靴,并且功能強大的二級緩存的實現(xiàn)啡莉,它擁有一系列的Cache接口裝飾者,可以滿足各種對緩存操作和更新的策略旨剥。 對于每個Cache而言咧欣,都有一個容量限制,MyBatis各供了各種策略來對Cache緩存的容量進行控制泞边,以及對Cache中的數(shù)據(jù)進行刷新和置換该押。如下類圖所示:

6. Mybatis整合第三方緩存框架

  • 我們系統(tǒng)為了提高系統(tǒng)并發(fā)性能,一般對系統(tǒng)進行分布式部署(集群部署方式)阵谚。
  • 不使用分布式緩存,緩存的數(shù)據(jù)在各個服務(wù)單獨存儲烟具,不方便系統(tǒng)開發(fā)梢什,所以要使用分布式緩存對緩存數(shù)據(jù)進行集中管理。
  • 第三方緩存框架一般有ehcache朝聋、memcache嗡午、redis緩存框架。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冀痕,一起剝皮案震驚了整個濱河市荔睹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帖烘,老刑警劉巖炮障,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萧朝,死亡現(xiàn)場離奇詭異,居然都是意外死亡吨拗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門婿斥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來劝篷,“玉大人,你說我怎么就攤上這事民宿〗考耍” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵活鹰,是天一觀的道長哈恰。 經(jīng)常有香客問我只估,道長,這世上最難降的妖魔是什么蕊蝗? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任仅乓,我火速辦了婚禮,結(jié)果婚禮上蓬戚,老公的妹妹穿的比我還像新娘夸楣。我一直安慰自己,他們只是感情好子漩,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布豫喧。 她就那樣靜靜地躺著,像睡著了一般幢泼。 火紅的嫁衣襯著肌膚如雪紧显。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天缕棵,我揣著相機與錄音孵班,去河邊找鬼。 笑死招驴,一個胖子當著我的面吹牛篙程,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播别厘,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼虱饿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了触趴?” 一聲冷哼從身側(cè)響起氮发,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冗懦,沒想到半個月后爽冕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡批狐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年扇售,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嚣艇。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡承冰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出食零,到底是詐尸還是另有隱情困乒,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布贰谣,位于F島的核電站娜搂,受9級特大地震影響迁霎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜百宇,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一考廉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧携御,春花似錦昌粤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至誓军,卻和暖如春袱讹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昵时。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工捷雕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壹甥。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓非区,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盹廷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容