一、問題原因
這些天在與朋友編寫業務邏輯的時候,發現了一個問題。當我們修改一個數據時,其他的數據也在跟着改變,研究了好久,才發現從地址上看,這些對象其實都是一個東西。但是他們都是從數據庫中查詢出來的,這個時候我們意識到Mybatis的緩存機制進行了一下簡單的研究。
二、緩存分類
從網上我們瞭解到,Mybatis的緩存分爲兩層,一級緩存與二級緩存。
一次緩存是基於SqlSession的,在同一個SqlSession下,如果我們調用了相同的Sql語句,那麼爲了效率的提高,持久化層將會給我們返回一個相同的對象。他在配置中是默認打開的。
二級緩存我理解爲一級緩存的拓展,對於Mybatis來說,二級緩存的開啓可以使不同Namespace的緩存相互共通,使緩存適用於整個項目,而不是一個單獨的Namespace,我瞭解到實現這種功能,還可以結合Redis或者ehcache諸如此類。他是默認關閉的。
三、一級緩存
由於一級緩存是默認打開的,所以我進一步的去做了幾個小的實驗,來看一看他的具體體現。
//生成SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//實例化接口
MyMapper myMapper = sqlSession.getMapper(MyMapper.class);
//一個簡單的按照ID的Select方法
Student a = myMapper.getBean(1);
Student b = myMapper.getBean(1);
按照這樣的查詢,我們最終得出的結果是
從這張圖我們可以看出,我們得出了兩個相同的對象。這就是Mybatis的一級緩存機制。
那麼有的時候緩存機制不是特別好用,例如當Spring整合Mybatis的時候
我們在這個時候,一般是@Autowired我們的Mybatis接口
在這個時候我們就算調用兩次相同的查詢,我們會發現結果也是兩個不同的對象。
這個時候好像是緩存失效了一樣。
在網上瞭解到,在整合的時候,每次查詢都會生成一個新的SqlSession對象,查詢開始生成,查詢結束銷燬。
這樣會導致每次SqlSession都不同,這樣也就引起了緩存失效
但是如果我們給業務邏輯增加了事務的話,例如
@Transactional (註解,開啓事務)
這樣的話作爲事務,要保證所有的操作在一個SqlSession下,那麼這樣一級緩存就恢復了它的效果。
另外有一點需要注意,當我們調用新增,修改和刪除的方法時,一級緩存防止髒讀會被清除。
四、二級緩存
因爲二級緩存需要主動開啓,一般在項目中也會與Redis諸如此類進行結合。
由於在實際項目開發中遇到的並不多,所以我瞭解的也不是很全面。
自己理解上來講,就是擴大了一級緩存的適用範圍。
由於二級緩存是默認關閉的,如果想進行開啓,需要如下幾步
1、首先在Mybatis中配置全局緩存開始
<setting name="cacheEnabled" value="true"/>
2、其次在映射文件中開始緩存
<cache/>
而且在開發過程中,我經常使用註解的方式去做查詢,所以對於二級緩存沒有去進行試驗,可能有一定的錯誤,歡迎指正。