mybatis 學習五 二級緩存不推薦使用

mybatis 二級緩存不推薦使用

    一 mybatis的緩存使用。

大致就是首先根據你的sqlid,參數的信息本身算出一個key值,而後你查詢的時候,會先把這個key值去緩存中找看有沒有value,若是有,直接返回出來,就不查詢db了。若是沒有,那麼查詢db,而後將key,value保存到緩存中,以便下次使用。

     1.1mybatis的一級緩存是基於sqlsession爲生命週期的

當你這個session沒有了,緩存就沒有了,其次當你sql執行!isselect語句的時候,緩存也會被直接所有清理掉以保證數據一致性。
  public int update(MappedStatement ms, Object parameter) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
    if (closed) throw new ExecutorException("Executor was closed.");
     //清理緩存
    clearLocalCache();
    return doUpdate(ms, parameter);
  }

 

     1.2 mybatis的二級緩存是基於application爲生命週期的

範圍是按照每一個namepace一個緩存來存貯和維護,同一個namespace放到一個緩存對象中,當這個namaspace中執行了!isselect語句的時候,整個namespace中的緩存所有清除掉。
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
     //清理緩存,而且!isselect語句的flushcache都是默認爲true的。
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }

 

 
如下摘抄自網絡觀點文字  http://blog.csdn.net/isea533/article/details/44566257

     3、Cache使用時的注意事項


1. 只能在【只有單表操做】的表上使用緩存

不僅是要保證這個表在整個系統中只有單表操做,並且和該表有關的所有操做必須所有在一個namespace下。

2. 在能夠保證查詢遠遠大於insert,update,delete操做的狀況下使用緩存

這一點不須要多說,全部人都應該清楚。記住,這一點須要保證在1的前提下才能夠!

4、避免使用二級緩存


可能會有不少人不理解這裏,二級緩存帶來的好處遠遠比不上他所隱藏的危害。

緩存是以namespace爲單位的,不一樣namespace下的操做互不影響。

insert,update,delete操做會清空所在namespace下的所有緩存。

一般使用MyBatis Generator生成的代碼中,都是各個表獨立的,每一個表都有本身的namespace。

爲何避免使用二級緩存

在符合【Cache使用時的注意事項】的要求時,並無什麼危害。

其餘狀況就會有不少危害了。

針對一個表的某些操做不在他獨立的namespace下進行。

例如在UserMapper.xml中有大多數針對user表的操做。可是在一個XXXMapper.xml中,還有針對user單表的操做。

這會致使user在兩個命名空間下的數據不一致。若是在UserMapper.xml中作了刷新緩存的操做,在XXXMapper.xml中緩存仍然有效,若是有針對user的單表查詢,使用緩存的結果可能會不正確。

更危險的狀況是在XXXMapper.xml作了insert,update,delete操做時,會致使UserMapper.xml中的各類操做充滿未知和風險。

有關這樣單表的操做可能不常見。可是你也許想到了一種常見的狀況。

多表操做必定不能使用緩存

爲何不能?

首先無論多表操做寫到那個namespace下,都會存在某個表不在這個namespace下的狀況。

例如兩個表:role和user_role,若是我想查詢出某個用戶的所有角色role,就必定會涉及到多表的操做。

<select id="selectUserRoles" resultType="UserRoleVO">
    select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>

 

像上面這個查詢,你會寫到那個xml中呢??

無論是寫到RoleMapper.xml仍是UserRoleMapper.xml,或者是一個獨立的XxxMapper.xml中。若是使用了二級緩存,都會致使上面這個查詢結果可能不正確。

若是你正好修改了這個用戶的角色,上面這個查詢使用緩存的時候結果就是錯的。

這點應該很容易理解。

在我看來,就以MyBatis目前的緩存方式來看是無解的。多表操做根本不能緩存。

若是你讓他們都使用同一個namespace(經過<cache-ref>)來避免髒數據,那就失去了緩存的意義。

看到這裏,實際上就是說,二級緩存不能用。整篇文章介紹這麼多也沒什麼用了。


5、挽救二級緩存?


想更高效率的使用二級緩存是解決不了了。

可是解決多表操做避免髒數據仍是有法解決的。解決思路就是經過攔截器判斷執行的sql涉及到那些表(能夠用jsqlparser解析),而後把相關表的緩存自動清空。可是這種方式對緩存的使用效率是很低的。

設計這樣一個插件是至關複雜的,既然我沒想着去實現,就不廢話了。

最後仍是建議,放棄二級緩存,在業務層使用可控制的緩存代替更好。
相關文章
相關標籤/搜索