1. 程式人生 > >mybatis二級快取不推薦使用

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

     三、Cache使用時的注意事項


1. 只能在【只有單表操作】的表上使用快取

不只是要保證這個表在整個系統中只有單表操作,而且和該表有關的全部操作必須全部在一個namespace下。

2. 在可以保證查詢遠遠大於insert,update,delete操作的情況下使用快取

這一點不需要多說,所有人都應該清楚。記住,這一點需要保證在1的前提下才可以!

四、避免使用二級快取


可能會有很多人不理解這裡,二級快取帶來的好處遠遠比不上他所隱藏的危害。

快取是以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>)來避免髒資料,那就失去了快取的意義。

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


五、挽救二級快取?


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

但是解決多表操作避免髒資料還是有法解決的。解決思路就是通過攔截器判斷執行的sql涉及到那些表(可以用jsqlparser解析),然後把相關表的快取自動清空。但是這種方式對快取的使用效率是很低的。

設計這樣一個外掛是相當複雜的,既然我沒想著去實現,就不廢話了。

最後還是建議,放棄二級快取,在業務層使用可控制的快取代替更好。