正如大多數持久層框架一樣,MyBatis 同樣提供了一級緩存和二級緩存的支持
1.一級緩存: 基於PerpetualCache 的 HashMap本地緩存,其存儲作用域爲 Session,當 Session flush 或 close 之後,該Session中的所有 Cache 就將清空。Session.clearCache()
2. 二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap存儲,不同在於其存儲作用域爲 Mapper(Namespace),並且可自定義存儲源,如 Ehcache。
3. 對於緩存數據更新機制,當某一個作用域(一級緩存Session/二級緩存Namespaces)的進行了 C/U/D 操作後,默認該作用域下所有 select 中的緩存將被clear。
一級緩存
現在進行一級緩存的測試
package sdibt.lxj.test;
import org.apache.ibatis.session.SqlSession;
import sdibt.lxj.dao.IBookDao;
import sdibt.lxj.util.MybatisUtils;
public class TestMybatisCache {
public static void main(String[] args) throws ClassNotFoundException {
SqlSession session = MybatisUtils.getSession();
IBookDao dao = session.getMapper(IBookDao.class);
//發出兩條查詢語句
System.out.println("進行第一次查詢");
dao.all();
System.out.println("進行第二次查詢");
dao.all();
}
}
測試結果,很明顯,在進行第二次查詢的時候已經將該查詢緩存了起來,不再執行sql,也就是說Mybatis默認是開啓一級緩存的,不過必須是同一個session纔有效
2018-07-08 15:50:42 [ main:0 ] - [ INFO ] {dataSource-1} inited
2018-07-08 15:50:42 [ main:54 ] - [ DEBUG ] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
進行第一次查詢
2018-07-08 15:50:42 [ main:80 ] - [ DEBUG ] Opening JDBC Connection
2018-07-08 15:50:42 [ main:82 ] - [ DEBUG ] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@9a7504c]
2018-07-08 15:50:42 [ main:90 ] - [ DEBUG ] ==> Preparing: select * from book
2018-07-08 15:50:42 [ main:139 ] - [ DEBUG ] ==> Parameters:
2018-07-08 15:50:42 [ main:165 ] - [ DEBUG ] <== Total: 7
進行第二次查詢
在查詢完一次加上session.clearCache();就把session內的緩存清空了
System.out.println("進行第一次查詢");
dao.all();
session.clearCache();
System.out.println("進行第二次查詢");
dao.all();
在測試一下如果對錶內的數據進行修改的話,緩存的查詢會不會存在
//發出兩條查詢語句
System.out.println("進行第一次查詢");
dao.all();
//刪除一條記錄
dao.delete1(7);
System.out.println("進行第二次查詢");
dao.all();
看來對錶進行修改會破壞一級緩存
2018-07-08 15:57:06 [ main:0 ] - [ INFO ] {dataSource-1} inited
2018-07-08 15:57:06 [ main:53 ] - [ DEBUG ] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
進行第一次查詢
2018-07-08 15:57:06 [ main:79 ] - [ DEBUG ] Opening JDBC Connection
2018-07-08 15:57:06 [ main:83 ] - [ DEBUG ] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@9a7504c]
2018-07-08 15:57:06 [ main:90 ] - [ DEBUG ] ==> Preparing: select * from book
2018-07-08 15:57:06 [ main:137 ] - [ DEBUG ] ==> Parameters:
2018-07-08 15:57:06 [ main:163 ] - [ DEBUG ] <== Total: 7
2018-07-08 15:57:06 [ main:164 ] - [ DEBUG ] ==> Preparing: delete from book where id=?
2018-07-08 15:57:06 [ main:165 ] - [ DEBUG ] ==> Parameters: 7(Integer)
2018-07-08 15:57:06 [ main:168 ] - [ DEBUG ] <== Updates: 1
進行第二次查詢
2018-07-08 15:57:06 [ main:168 ] - [ DEBUG ] ==> Preparing: select * from book
2018-07-08 15:57:06 [ main:168 ] - [ DEBUG ] ==> Parameters:
2018-07-08 15:57:06 [ main:171 ] - [ DEBUG ] <== Total: 6
二級緩存
mybatis使用二級緩存的話只需要在mapper標籤裏面加一個<cache/>
測試二級緩存,二級緩存是跨session的,如果使用二級緩存,則必須要提交事務
package sdibt.lxj.test;
import org.apache.ibatis.session.SqlSession;
import sdibt.lxj.dao.IBookDao;
import sdibt.lxj.util.MybatisUtils;
public class TestMybatisCache {
public static void main(String[] args) throws ClassNotFoundException {
//創建兩個session
SqlSession session = MybatisUtils.getSession();
SqlSession session1 = MybatisUtils.getSession();
IBookDao dao = session.getMapper(IBookDao.class);
IBookDao dao1 = session1.getMapper(IBookDao.class);
dao.all();
//提交事務
session.commit();
dao1.all();
session1.commit();
}
}
2018-07-08 17:31:21 [ main:0 ] - [ INFO ] {dataSource-1} inited
2018-07-08 17:31:21 [ main:40 ] - [ DEBUG ] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2018-07-08 17:31:21 [ main:101 ] - [ DEBUG ] Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.0
2018-07-08 17:31:21 [ main:108 ] - [ DEBUG ] Opening JDBC Connection
2018-07-08 17:31:21 [ main:111 ] - [ DEBUG ] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4923ab24]
2018-07-08 17:31:21 [ main:120 ] - [ DEBUG ] ==> Preparing: select * from book
2018-07-08 17:31:21 [ main:166 ] - [ DEBUG ] ==> Parameters:
2018-07-08 17:31:21 [ main:197 ] - [ DEBUG ] <== Total: 7
2018-07-08 17:31:21 [ main:265 ] - [ DEBUG ] Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.5
實驗,當某一個session對數據庫進行了修改,其他session共享的二級緩存是否失效
package sdibt.lxj.test;
import org.apache.ibatis.session.SqlSession;
import sdibt.lxj.dao.IBookDao;
import sdibt.lxj.util.MybatisUtils;
public class TestMybatisCache {
public static void main(String[] args) throws ClassNotFoundException {
//創建兩個session
SqlSession session = MybatisUtils.getSession();
SqlSession session1 = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
IBookDao dao = session.getMapper(IBookDao.class);
IBookDao dao1 = session1.getMapper(IBookDao.class);
IBookDao dao2 = session2.getMapper(IBookDao.class);
dao.all();
//提交事務
session.commit();
dao2.delete1(1);
session.commit();
dao1.all();
session1.commit();
}
}
可以看到,在某一個 session執行了修改數據庫的方法,仍然能命中緩存,說明二級緩存是不再session中的,所以如果要使用二級緩存,應該是一些不經常更新的數據
2018-07-08 17:35:17 [ main:0 ] - [ INFO ] {dataSource-1} inited
2018-07-08 17:35:17 [ main:38 ] - [ DEBUG ] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2018-07-08 17:35:18 [ main:100 ] - [ DEBUG ] Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.0
2018-07-08 17:35:18 [ main:106 ] - [ DEBUG ] Opening JDBC Connection
2018-07-08 17:35:18 [ main:110 ] - [ DEBUG ] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4923ab24]
2018-07-08 17:35:18 [ main:119 ] - [ DEBUG ] ==> Preparing: select * from book
2018-07-08 17:35:18 [ main:163 ] - [ DEBUG ] ==> Parameters:
2018-07-08 17:35:18 [ main:194 ] - [ DEBUG ] <== Total: 7
2018-07-08 17:35:18 [ main:207 ] - [ DEBUG ] Opening JDBC Connection
2018-07-08 17:35:18 [ main:207 ] - [ DEBUG ] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@710726a3]
2018-07-08 17:35:18 [ main:209 ] - [ DEBUG ] ==> Preparing: delete from book where id=?
2018-07-08 17:35:18 [ main:209 ] - [ DEBUG ] ==> Parameters: 1(Integer)
2018-07-08 17:35:18 [ main:210 ] - [ DEBUG ] <== Updates: 0
2018-07-08 17:35:18 [ main:213 ] - [ DEBUG ] Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.5