2019年4月20日 星期六

一、二級快取,整合 Ehcache 2.x (Mybatis3.x 十三)

<setting name="cacheEnabled" value="true" /> <!-- 二級快取的開關 -->
<setting name="localCacheScope" value="STATEMENT" /> <!-- 一級快取的範圍,SESSION為開;STATEMENT為關 -->

※一級快取預設是 SESSION,表示 SqlSession;二級快取預設是 true

※SESSION 表示每個一個 Session 中的所有語句都可以共享; STATEMENT 表示只有當前的  SQL 語句的結果可以共享 (看最下面的一、二級快取)


測試類
InputStream is = null;
SqlSession sqlSession = null;
SqlSession sqlSession2 = null;
try {
    is = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    sqlSession = factory.openSession();
    DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
    //一級快取
    Dept dept1 = mapper.getDeptById(40);
    //sqlSession.clearCache();清一級快取
    //增刪改操作之後也不會有快取
    Dept dept2 = mapper.getDeptById(40);
    //Dept dept2 = mapper.getDeptByIdAndLoc(40, "BOSTON");
    System.out.println(dept1 == dept2);
    
    //二級快取
    /*
    sqlSession2 = factory.openSession();
    DeptMapper mapper2 = sqlSession2.getMapper(DeptMapper.class);
    Dept dept2 = mapper2.getDeptById(40);
    System.out.println(dept1 == dept2);
    */
}
// ...

注意 dept1 == dept2,如果資料庫沒有值得到的結果是 null,那兩個判斷是 true


※一級快取:

1.指同一個 SqlSession 做查詢的快取
2.只有 where 條件一樣時,才有快取(如上的例子,就算回傳結果一樣,還是沒快取)
兩個查詢之間有增刪改和呼叫 SqlSession 的 clearCache 方法,都不會有快取


※二級快取:

1..指不同 SqlSession 做查詢的快取
2.使用 <cache /> 設定二級快取,其中的屬性可看官網的介紹,其中 readOnly 預設是 false,如果是 false,resultType 的 java bean 必需 implements Serializable,否則會報 java.io.NotSerializableException 的錯,而反序列化後,SQL 就是兩條了,就沒有快取了
3.二個查詢之間必須要將第一個快取 close()後,才會將一級快取裡的值移到二級快取,所以不關閉就不會成功
select 標籤有 useCache,當全域的二級快取是開時,可以針對不想二級快取的 select 關閉
4.<cache-ref> 使用在用另外一支 xml 的 cache


※一、二級快取

在 select 標籤中,還有個 flushCache 可以針對一、二級快取做清除的動作

如果一級快取是 STATEMENT;二級快取是 true,一級快取 close()後會將資料移到二級快取,但一級快取之間還是無法共享

sqlSession = factory.openSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
    
//一級快取(SqlSession快取)
Dept dept1 = mapper.getDeptById(40);
Dept dept2 = mapper.getDeptById(40);
System.out.println(dept1 == dept2); // false
    
sqlSession.close();
    
sqlSession2 = factory.openSession();
DeptMapper mapper2 = sqlSession2.getMapper(DeptMapper.class);
    
Dept dept3 = mapper2.getDeptById(40);
//System.out.println(dept1 == dept3);
System.out.println(dept1 == dept3); // false
System.out.println(dept2 == dept3); // true

※如果注解 dept2,那 dept1 == dept3 會是 true,因為 STATEMENT 代表當前的語句



※整合 Ehcache2.x

官方文檔,要下載 ehcache2 和 mybatis 和 ehcache 的 jar 檔, 在根目錄要有 ehcache.xml,可去 ehcache 官網下載,至於設定的意思,可以看到 This file can also be downloaded from 後面有個超連結,會有解釋的;或者 2.x 的 PDF 裡都有
要使用時,只要在二級快取的標籤有個 type,指定為 ehcache 就可以了

<cache readOnly="true" type="org.mybatis.caches.ehcache.EhcacheCache" />

※因為使用 <cache> 標籤,所以還是二級快取,一切的行為都和二級快取一樣,但 ehcache.xml 有一個 <diskStore path="aaa.bbb">,這裡面打的 aaa.bbb 並不是 aaa 目錄下有 bbb 目錄,而是 aaa.bbb 的目錄,會出現在 src 下,也可改成磁碟的路徑,這個檔案就算將二級快取關閉,還是會出現,但是行為還是二級快取的行為

※P.S. 我在整合 Ehcache 3.x 的時候,我試了最低的版本和目前最高的版本,XML 都有問題,都會報 Element <ehcache:config> does not allow attribute "xmlns:ehcache" 或 Element <config> does not allow attribute "xmlns:xsi"

沒有留言:

張貼留言