一、MyBatis緩存介紹
正如大多數(shù)持久層框架一樣,MyBatis 同樣提供了一級緩存和二級緩存的支持
1.一級緩存:
基于PerpetualCache 的 HashMap本地緩存,其存儲作用域為 Session,當 Session flush 或 close 之后,該Session中的所有 Cache 就將清空。
2. 二級緩存:
二級緩存與一級緩存其機制相同,默認也是采用 PerpetualCache,HashMap存儲,不同在于其存儲作用域為 Mapper(Namespace),并且可自定義存儲源,如 Ehcache。
3. 對于緩存數(shù)據(jù)更新機制,當某一個作用域(一級緩存Session/二級緩存Namespaces)的進行了 C/U/D 操作后,默認該作用域下所有 select 中的緩存將被clear。
1.1、Mybatis一級緩存測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package me.gacl.test; import me.gacl.domain.User; import me.gacl.util.MyBatisUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; /** * @author gacl * 測試一級緩存 */ public class TestOneLevelCache { /* * 一級緩存: 也就Session級的緩存(默認開啟) */ @Test public void testCache() { SqlSession session = MyBatisUtil.getSqlSession(); String statement = "me.gacl.mapping.userMapper.getUser"; User user = session.selectOne(statement, ); System.out.println(user); /* * 一級緩存默認就會被使用 */ user = session.selectOne(statement, ); System.out.println(user); session.close(); /* . 必須是同一個Session,如果session對象已經close()過了就不可能用了 */ session = MyBatisUtil.getSqlSession(); user = session.selectOne(statement, ); System.out.println(user); /* . 查詢條件是一樣的 */ user = session.selectOne(statement, ); System.out.println(user); /* . 沒有執(zhí)行過session.clearCache()清理緩存 */ //session.clearCache(); user = session.selectOne(statement, ); System.out.println(user); /* . 沒有執(zhí)行過增刪改的操作(這些操作都會清理緩存) */ session.update( "me.gacl.mapping.userMapper.updateUser" , new User(, "user" , )); user = session.selectOne(statement, ); System.out.println(user); } } |
1.2、Mybatis二級緩存測試
1、開啟二級緩存,在userMapper.xml文件中添加如下配置
1
2
3
|
<mapper namespace= "me.gacl.mapping.userMapper" > <!-- 開啟二級緩存 --> <cache/> |
2、測試二級緩存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package me.gacl.test; import me.gacl.domain.User; import me.gacl.util.MyBatisUtil; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Test; /** * @author gacl * 測試二級緩存 */ public class TestTwoLevelCache { /* * 測試二級緩存 * 使用兩個不同的SqlSession對象去執(zhí)行相同查詢條件的查詢,第二次查詢時不會再發(fā)送SQL語句,而是直接從緩存中取出數(shù)據(jù) */ @Test public void testCache() { String statement = "me.gacl.mapping.userMapper.getUser" ; SqlSessionFactory factory = MyBatisUtil.getSqlSessionFactory(); //開啟兩個不同的SqlSession SqlSession session = factory.openSession(); SqlSession session = factory.openSession(); //使用二級緩存時,User類必須實現(xiàn)一個Serializable接口===> User implements Serializable User user = session.selectOne(statement, ); session.commit(); //不懂為啥,這個地方一定要提交事務之后二級緩存才會起作用 System.out.println( "user=" +user); //由于使用的是兩個不同的SqlSession對象,所以即使查詢條件相同,一級緩存也不會開啟使用 user = session.selectOne(statement, ); //session.commit(); System.out.println( "user=" +user); } } |
1.3、二級緩存補充說明
1. 映射語句文件中的所有select語句將會被緩存。
2. 映射語句文件中的所有insert,update和delete語句會刷新緩存。
3. 緩存會使用Least Recently Used(LRU,最近最少使用的)算法來收回。
4. 緩存會根據(jù)指定的時間間隔來刷新。
5. 緩存會存儲1024個對象
cache標簽常用屬性:
1
2
3
4
5
|
<cache eviction= "FIFO" <!--回收策略為先進先出--> flushInterval= "60000" <!--自動刷新時間60s--> size= "512" <!--最多緩存 512 個引用對象--> readOnly= "true" /> <!--只讀--> |
給大家補充點知識:
和hibernate一樣,mybatis也有緩存機制
一級緩存是基于 PerpetualCache(mybatis自帶)的 HashMap 本地緩存,作用范圍為session,所以當session commit或close后,緩存就會被清空
二級緩存默認也是基于 PerpetualCache,但是可以為其制定存儲源,比如ehcache
一級緩存緩存的是SQL語句,而二級緩存緩存的是結果對象,看如下例子(mybatis的日志級別設為debug)