Mybatis的一、二級快取
MyBatis快取介紹
Mybatis和Hibernate一樣,也有一級和二級快取,同樣預設開啟的只有一級快取,二級快取也需要手動配置開啟。
Mybatis 提供了快取機制減輕資料庫壓力,提高資料庫效能
- 一級快取: 基於PerpetualCache 的 HashMap本地快取,其儲存作用域為 Session,當 Session flush 或 close 之後,該Session中的所有 Cache 就將清空。
- 二級快取與一級快取其機制相同,預設也是採用 PerpetualCache,HashMap儲存,不同在於其儲存作用域為 Mapper(Namespace)
- 對於快取資料更新機制,當某一個作用域(一級快取Session/二級快取Namespaces)的進行了 C/U/D 操作後,預設該作用域下所有 select 中的快取將被clear。
一、一級快取(預設是開啟的)
一級快取是SqlSession級別的快取,快取的資料只在SqlSession內有效。
每個與資料庫的連結SqlSession會話都有各自自己的快取,這些一級快取之間是不能通訊的,是相互獨立的快取空間!
1)必須是同一個SqlSession會話, 發起一條sql語句
SqlSession session = sqlSessionFactory.openSession(); try { UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.getUser(1); System.out.println(user.getUsername()); User user2 = userMapper.getUser(1); System.out.println(user2.getUsername()); } finally { session.close(); }
2)SqlSession清理快取, 發起一兩sql語句
同一個sqlsession,查詢相同id的user,查詢中間,做了SqlSession清理快取,或者增改刪操作,都會發起兩條sql語句,
用不同的sqlsession,查詢同一個id的user,也會發起兩條sql語句。
User user = userMapper.getUser(1); System.out.println(user.getUsername()); session.clearCache(); User user2 = userMapper.getUser(1); System.out.println(user2.getUsername());
在操作資料庫的時候需要先建立SqlSession會話物件,在物件中有一個HashMap用於儲存快取資料,此HashMap是當前會話物件私有的,別的SqlSession會話物件無法訪問。
具體流程:
1.第一次執行select完畢會將查到的資料寫入SqlSession內的HashMap中快取起來
2.第二次執行select會從快取中查資料,如果select相同切傳引數一樣,那麼就能從快取中返回資料,不用去資料庫了,從而提高了效率
注意事項:
1.如果SqlSession執行了DML操作(insert、update、delete),並commit了,那麼mybatis就會清空當前SqlSession快取中的所有快取資料,這樣可以保證快取中的存的資料永遠和資料庫中一致,避免出現髒讀
2.當一個SqlSession結束後那麼他裡面的一級快取也就不存在了,mybatis預設是開啟一級快取,不需要配置
3.mybatis的快取是基於[namespace:sql語句:引數]來進行快取的,意思就是,SqlSession的HashMap儲存快取資料時,是使用[namespace:sql:引數]作為key,查詢返回的語句作為value儲存的。
二、二級快取(需要手動配置開啟)
1.二級快取是mapper級別的快取,同一個namespace公用這一個二級快取,所以對SqlSession是共享的。
2.一級快取的生命週期隨著一次會話session的關閉而清空,開啟二級快取的情況下,一級快取裡的資料,在清空或者提交之前會轉存到二級快取的空間中繼續存在。
3.當一次會話sqlsession的快取裡如果存放著兩個不同型別的物件,比如User和Role物件,當一級快取清空之前,開起二級快取的情況下,它們兩個物件會分別存入各自的名稱空間的二級快取空間中;在二級快取中兩個物件是分別放在兩個獨立的Map物件裡的(各自的快取空間裡)。
開啟二級快取步驟:
1、全域性配置檔案中開啟二級快取
<settings>
<!-- 開啟二級快取 -->
<setting name="cacheEnabled" value="true"/>
</settings>
2、在sql對映檔案中新增一個標籤<cache/>, 即開啟了這個namespace檔案的二級快取
<mapper namespace="cn.jq.mybatis.dao.UserMapper">
<!-- 開啟二級快取 -->
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true" />
<cache/>這個標籤中有關的屬性:
eviction可用的收回策略有:
- LRU(預設值) – 最近最少使用的:移除最長時間不被使用的物件。
- FIFO – 先進先出:按物件進入快取的順序來移除它們。
- SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。
- WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。
flushInterval(重新整理間隔)
可以被設定為任意的正整數,而且它們代表一個合理的毫秒 形式的時間段。預設情況是不設定,也
就是沒有重新整理間隔,快取僅僅呼叫語句時重新整理。
size(引用數目,預設值1024)
可以被設定為任意正整數,要記住你快取的物件數目和你執行環境的 可用記憶體資源數目。。
readOnly(只讀)屬性可以被設定為 true 或 false(預設)。
只讀的快取會給所有呼叫者返回緩 存物件的相同例項。因此這些物件不能被修改。這提供了很重
要的效能優勢。可讀寫的快取 會返回快取物件的拷貝(通過序列化) 。
3、Mybatis的二級快取使用的序列化介面,所以,POJO類就必須實現序列化介面
public class User implements Serializable{
private static final long serialVersionUID = 1L;
測試:發起一條sql語句,
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.getUser(1);
System.out.println(user.getUsername());
session.close(); //第一個會話關閉之前,清空一級快取資料,同時轉存到二級快取
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = session2.getMapper(UserMapper.class);
User user2 = userMapper2.getUser(1);
System.out.println(user2.getUsername());
session2.close();
具體流程:
1.當一個sqlseesion執行了一次select後,在關閉此session的時候,會將查詢結果快取到二級快取
2.當另一個sqlsession執行select時,首先會在他自己的一級快取中找,如果沒找到,就回去二級快取中找,找到了就返回,就不用去資料庫了,從而減少了資料庫壓力提高了效能
注意事項:
1.如果SqlSession執行了DML操作(insert、update、delete),並commit了,那麼mybatis就會清空當前mapper快取中的所有快取資料,這樣可以保證快取中的存的資料永遠和資料庫中一致,避免出現髒讀
2.mybatis的快取是基於[namespace:sql語句:引數]來進行快取的,意思就是,SqlSession的HashMap儲存快取資料時,是使用[namespace:sql:引數]作為key,查詢返回的語句作為value儲存的。
總結:
1.全域性變數配置cacheEnabled:
ture(預設):開啟二級快取,
false:關閉二級快取,但一級快取不受影響
2.對映檔案中mapper標籤下<cache/>:
配置有:開啟二級快取
沒配置有:關閉二級快取,一級快取不受影響
3.每個select標籤都可以設定 useCache 屬性:
true(預設):上面1和2開啟二級快取後,二級快取生效
false:哪怕上面1和2開啟了二級快取,二級快取在這個select也會失效,
一級快取不受影響
4.增改刪查標籤都可以設定flushCache屬性:
增改刪true(預設):執行增改刪操作後,重新整理快取,把原來的快取幹掉,
注意這個設定有點特殊,幹掉的快取包括一、二級快取
查false(預設):如果在查詢標籤上把它設定為true,等於禁用所有快取
5.全部變數 localCacheScope(瞭解):
SESSION(預設)開啟一級快取
STATEMENT:如果設定為這裡,相當於關閉一級快取