Mybatis 框架總結(五) :緩存機制

正如大多數持久層框架一樣,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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章