mybatis學習-緩存的使用和理解

理解mybatis中緩存

一級緩存(本地緩存):sqlSession級別的緩存,一級緩存一直都是開啓的,sqlSession級別的Map,與數據庫同一次回話期間查詢到的數據都會放在本地緩存當中,以後如果要查詢相同的數據,直接從緩存當中獲取,而不要向數據庫發送請求獲得數據了。

//一級緩存的體驗

@Test
public void test05() throws IOException {
	SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	try {
		EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
		//根據id查詢數據
		 Employee employee = employeeMapper.getEmployeeById(1);
		 System.out.println(employee);
		 //再次查詢
		 Employee employee2 = employeeMapper.getEmployeeById(1);
		 System.out.println(employee2);
	} finally {
		sqlSession.close();
	}	
}

查詢的結果:只會向數據庫發送一次請求。

DEBUG 04-15 22:17:55,203 ==>  Preparing: SELECT `id`, `lastname`, `email`, `birth`, `createtime`, `emp_image`, `department_id` FROM `employee` WHERE id=?   (BaseJdbcLogger.java:145) 
DEBUG 04-15 22:17:55,292 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 04-15 22:17:55,328 <==      Total: 1  (BaseJdbcLogger.java:145) 
Employee [id=1, lastname=劉東平, [email protected], birth=Wed Mar 27 19:50:12 CST 2019, createtime=Wed Mar 27 19:50:16 CST 2019, emp_image=, department=null]
Employee [id=1, lastname=劉東平, [email protected], birth=Wed Mar 27 19:50:12 CST 2019, createtime=Wed Mar 27 19:50:16 CST 2019, emp_image=, department=null]

思考:那些情況,一級緩存會失效?
1.sqlSession對象不是同一個對象了,就是說出現了兩次會話了。
2.如果sqlSession相同,但是查詢的條件不同,很顯然還是會發送請求,因爲你的緩存中沒有數據,所以查詢條件不同,還會進行。
3.如果sqlSession相同,但是在期間進行了增刪改,那麼也會發送sql語句,因爲進行數據庫操作必然會發送變化。
4.如果sqlSession相同,但是我們手動清除了緩存(sqlSession.clearCache()。


*二級緩存(全局緩存):*二級緩存是基於namespace級別的緩存機制,也就是說一個namespace就對應着一個的二級緩存。
二級緩存的工作機制:
1.一個會話,查詢一條數據。這個數據就會放在當前會話的一級緩存當中,
2.如果該會話關閉了,一級緩存中保存的數據會保存到二級緩存中,新的回話查詢信息,就可以參照二級緩存中的數據進行,選擇性的知道自己是否該發送sql語句了
3.sqlSession===EmployeeMapper=>Employee
sqlSession
=>DepartmentMapper=>department
不同的namespace查出的數據會保存在自己的緩存當中(Map)

二級緩存(second level cache),全局作用域緩存
• 二級緩存默認不開啓,需要手動配置
• MyBatis提供二級緩存的接口以及實現,緩存實現要求
POJO實現Serializable接口
• 二級緩存在 SqlSession 關閉或提交 之後纔會 生效

怎麼使用二級緩存
1.需要在mybatis-config.xml配置文件中配置:

<settings>.
		<setting name="cacheEnabled" value="true"/>
</setteings>

2.需要在xxxxMapper.xml文件內配置

 	<cache></cache>

3.每個pojo都必須實現序列化接口

• 使用步驟
– 1、全局配置文件中開啓二級緩存

• <setting name= "cacheEnabled" value="true"/>

– 2、需要使用二級緩存的映射文件處使用cache配置緩存

• <cache />

– 3、注意:POJO需要實現Serializable接

緩存相關屬性
• eviction=“ FIFO” :緩存回收策略:

  LRU – 最近最少使用的:移除最長時間不被使用的對象。
 FIFO – 先進先出:按對象進入緩存的順序來移除它們。
 SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。
  WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。
 默認的是 LRU

。*
• flushInterval :刷新間隔,單位毫秒

默認情況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新

• size :引用數目,正整數 代表緩存最多可以存儲多少個對象,太大容易導致內存溢出
• readOnly :只讀,true/false

 true:只讀緩存;會給所有調用者返回緩存對象的相同實例。因此這些對象
不能被修改。這提供了很重要的性能優勢。
     false:讀寫緩存;會返回緩存對象的拷貝(通過序列化)。這會慢一些,
但是安全,因此默認是 false。

1、全局setting的cacheEnable:

– 配置二級緩存的開關。一級緩存一直是打開的。

• 2、select標籤的useCache屬性:

– 配置這個select是否使用二級緩存。一級緩存一直是使用的

• 3、sql標籤的flushCache屬性:

– 增刪改默認flushCache=true。sql執行以後,會同時清空一級和二級緩存。

  查詢默認flushCache=false。

• 4、sqlSession.clearCache():

– 只是用來清除一級緩存。

• 5、當在某一個作用域

 (一級緩存Session/二級緩存 Namespaces) 進行了
  C/U/D 操作後,默認該作用域下 所有  select  中的緩存將被 clear

配置之後體驗二級緩存

//二級緩存的體驗
	@Test
	public void test06() throws IOException {
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		SqlSession sqlSession = sqlSessionFactory.openSession(true);
		SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
		try {
			EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
			EmployeeMapper employeeMapper2 = sqlSession2.getMapper(EmployeeMapper.class);
			//根據id查詢數據
			Employee employee = employeeMapper.getEmployeeById(1);
			System.out.println(employee);
			sqlSession.close();
			//再次查詢
			Employee employee2 = employeeMapper2.getEmployeeById(1);
			System.out.println(employee2);
			
		} finally {
			sqlSession2.close();
		}	
	}

查詢的打印結果:只會打印一條SQL語句

DEBUG 04-15 23:09:50,016 Cache Hit Ratio [com.ldp.mybatis.dao.EmployeeMapper]: 0.0  (LoggingCache.java:62) 
DEBUG 04-15 23:09:50,026 ==>  Preparing: SELECT `id`, `lastname`, `email`, `birth`, `createtime`, `emp_image`, `department_id` FROM `employee` WHERE id=?   (BaseJdbcLogger.java:145) 
DEBUG 04-15 23:09:50,092 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 04-15 23:09:50,127 <==      Total: 1  (BaseJdbcLogger.java:145) 
Employee [id=1, lastname=劉東平, [email protected], birth=Wed Mar 27 19:50:12 CST 2019, createtime=Wed Mar 27 19:50:16 CST 2019, emp_image=, department=null]
DEBUG 04-15 23:09:50,257 Cache Hit Ratio [com.ldp.mybatis.dao.EmployeeMapper]: 0.5  (LoggingCache.java:62) 
Employee [id=1, lastname=劉東平, [email protected], birth=Wed Mar 27 19:50:12 CST 2019, createtime=Wed Mar 27 19:50:16 CST 2019, emp_image=, department=null]

細節:第一次查詢的會話完畢或者關閉後,一級緩存中的數據纔會轉移到二級緩存當中。

緩存相關的設置:
1.cacheEnabled=true|false 關閉的是二級緩存,一級緩存一直都會存在。
2.每個select標籤都會有useCache=true|false:不使用二級緩存。不影響一級緩存
3.每個增刪改上面也會有flushCache=true||false
增刪改執行完之後,清除緩存
測試:爲true 一級緩存會被清除,二級必然也會清除。
查詢標籤也會有相應的情況出現:
4.sqlSession.clearCache:只是清除當前sqlSession的一級緩存
5.localCacheScope(本地緩存):(一級緩存session)存放數據

**

一級緩存和二級緩存的總結:

在這裏插入圖片描述

**
第三方(ehcache)的二級緩存實現:
1.導入第三方的緩存包ehcache-core-2.6.8.jar
2.導入整合包mybatis-ehcache-1.0.3.jar 兩個日誌包slf4j-api-1.6.1.jar… slf4j-log4j12-1.6.2.jar
3.加入ehcache.xml文件
4.在需要添加二級緩存的配置文件添加

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

其中ehcache.xml文件內容

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 <!-- 磁盤保存路徑 -->
 <diskStore path="D:\44\ehcache" />
 
 <defaultCache 
   maxElementsInMemory="10000" 
   maxElementsOnDisk="10000000"
   eternal="false" 
   overflowToDisk="true" 
   timeToIdleSeconds="120"
   timeToLiveSeconds="120" 
   diskExpiryThreadIntervalSeconds="120"
   memoryStoreEvictionPolicy="LRU">
 </defaultCache>
</ehcache>
 
<!-- 
屬性說明:
l diskStore:指定數據在磁盤中的存儲位置。
l defaultCache:當藉助CacheManager.add("demoCache")創建Cache時,EhCache便會採用<defalutCache/>指定的的管理策略
 
以下屬性是必須的:
l maxElementsInMemory - 在內存中緩存的element的最大數目 
l maxElementsOnDisk - 在磁盤上緩存的element的最大數目,若是0表示無窮大
l eternal - 設定緩存的elements是否永遠不過期。如果爲true,則緩存的數據始終有效,如果爲false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷
l overflowToDisk - 設定當內存緩存溢出的時候是否將過期的element緩存到磁盤上
 
以下屬性是可選的:
l timeToIdleSeconds - 當緩存在EhCache中的數據前後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,這些數據便會刪除,默認值是0,也就是可閒置時間無窮大
l timeToLiveSeconds - 緩存element的有效生命期,默認是0.,也就是element存活時間無窮大
 diskSpoolBufferSizeMB 這個參數設置DiskStore(磁盤緩存)的緩存區大小.默認是30MB.每個Cache都應該有自己的一個緩衝區.
l diskPersistent - 在VM重啓的時候是否啓用磁盤保存EhCache中的數據,默認是false。
l diskExpiryThreadIntervalSeconds - 磁盤緩存的清理線程運行間隔,默認是120秒。每個120s,相應的線程會進行一次EhCache中數據的清理工作
l memoryStoreEvictionPolicy - 當內存緩存達到最大,有新的element加入的時候, 移除緩存中element的策略。默認是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出)
 -->
發佈了29 篇原創文章 · 獲贊 4 · 訪問量 5272
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章