【Mybatis框架】查詢緩存(二級緩存)

 繼上一篇博客,咱們講述了mybatis的一級緩存,接下來,咱們來學習一下mybatis的二級緩存html

博客連接地址: http://blog.csdn.NET/liweizhong193516/article/details/53639350 java

 

按照慣例,先來一張形象一點的圖:mysql

       二級緩存區域是根據mapper的namespace劃分的,相同namespace的mapper查詢數據放在同一個區域,若是使用mapper代理方法每一個mapper的namespace都不一樣,此時能夠理解爲二級緩存區域是根據mapper劃分,也就是根據命名空間來劃分的,若是兩個mapper文件的命名空間同樣,那樣,他們就能夠共享一個mapper緩存。web

       每次查詢會先從緩存區域找,若是找不到從數據庫查詢,查詢到數據將數據寫入緩存。sql

Mybatis內部存儲緩存使用一個HashMap,key爲hashCode+sqlId+Sql語句。value爲從查詢出來映射生成的Java對象數據庫

 

       sqlSession執行insert、update、delete等操做commit提交後會清空緩存區域。緩存

 

開啓緩存:

在這特別提醒一下,Mybatis的二級緩存是須要配置來開啓的,咱們須要在Mybatis的核心配置文件SqlMapConfig.xml中加入:安全

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <span style="font-size:18px;"><setting name="cacheEnabled" value="true"/></span>  

 

而後還要在Mapper映射文件中添加一行:session

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <span style="font-size:18px;"><cache/> <!--<span >表示此mapper開啓二級緩存--></span></span>  
假如說,已開啓二級緩存的Mapper中有個statement要求禁用怎麼辦,那也不難,只須要在statement中設置useCache=false就能夠禁用當前select語句的二級緩存,也就是每次都會生成sql去查詢,ps:默認狀況下默認是true,也就是默認使用二級緩存

 

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <span style="font-size:18px;"><select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false"></span>  

 

刷新緩存:

在mapper的同一個namespace中,若是有其餘insert、update、delete操做後都須要執行刷新緩存操做,來避免髒讀。這時咱們只須要設置statement配置中的flushCache=「true「屬性,就會默認刷新緩存,相反若是是false就不會了。固然,無論開不開緩存刷新功能,你要是手動更改數據庫表,那都確定不能避免髒讀的發生,那就屬於手賤了。mybatis

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <span style="font-size:18px;"><insert id="insertUser" parameterType="cn.ssm.mybatis.po.User" flushCache="true"></span>  
 那既然可以刷新緩存,能定時刷新嗎?也就是設置時間間隔來刷新緩存,答案是確定的。咱們在mapper映射文件中添加<cache/>來表示開啓緩存,那接下來,只須要咱們在配置flushinterval(刷新間隔)就哦了:
[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <span style="font-size:18px;"><cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/></span>  
flushInterval(刷新間隔)能夠被設置爲任意的正整數,並且它們表明一個合理的毫秒形式的時間段。默認狀況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新。 size(引用數目)能夠被設置爲任意正整數,要記住你緩存的對象數目和你運行環境的可用內存資源數目。默認值是1024。 readOnly(只讀)屬性能夠被設置爲true或false。只讀的緩存會給全部調用者返回緩存對象的相同實例。所以這些對象不能被修改。這提供了很重要的性能優點。可讀寫的緩存會返回緩存對象的拷貝(經過序列化)。這會慢一些,可是安全,所以默認是false。

 

 

而這個例子更高級的配置建立了一個 FIFO 緩存,並每隔 60 秒刷新,存數結果對象或列表的 512 個引用,並且返回的對象被認爲是隻讀的,所以在不一樣線程中的調用者之間修改它們會致使衝突。可用的收回策略有, 默認的是 LRU:

1.      LRU – 最近最少使用的:移除最長時間不被使用的對象。

2.      FIFO – 先進先出:按對象進入緩存的順序來移除它們。

3.      SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。

4.      WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。

這就是咱們軟考擅長的東西了,不用解釋了吧!

 

說了這麼多,擺個例子來結束本篇博文:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. //獲取session1  
  2.     SqlSession session1 = sqlSessionFactory.openSession();  
  3.     UserMapper userMapper = session1.getMapper(UserMapper.class);  
  4. //使用session1執行第一次查詢  
  5.     User user1 = userMapper.findUserById(1);  
  6.     System.out.println(user1);  
  7. //關閉session1  
  8.     session1.close();  
  9. //獲取session2  
  10.     SqlSession session2 = sqlSessionFactory.openSession();  
  11.     UserMapper userMapper2 = session2.getMapper(UserMapper.class);  
  12. //使用session2執行第二次查詢,因爲開啓了二級緩存這裏從緩存中獲取數據再也不向數據庫發出sql  
  13.     User user2 = userMapper2.findUserById(1);  
  14.     System.out.println(user2);  
  15. //關閉session2  
  16.     session2.close();  
運行效果:

 

而若是咱們在一、2之間執行一次commit操做,就變成了:

 

 

因而可知,Mybatis的二級緩存是跨Session的,每一個Mapper享有同一個二級緩存域,一樣,每次執行commit操做以後,一樣會清空緩存。

 

Mybatis這麼好,如何應用呢?

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

但是,好歸好,Mybatis也有它必定的侷限性。那就是Mybatis對於細粒度的數據級別的緩存實現的不是太好,也就是若是同Mapper下的商品類別繁多的話,他不能實現只刷新某固定商品的信息,而只能全盤刷新。當時將這塊的時候我想過讓Mapper水平分區不就好了,但是後來講到Mybatis的二級緩存是以命名空間劃分的或者說是以Mapper劃分,無論咱們怎麼水平劃分,只要命名空間同樣,那就只共享一個二級緩存域,當刷新的時候仍是會全Mapper更新一遍。

相關文章
相關標籤/搜索