1. 程式人生 > >mybatis學習筆記(八)- 快取機制

mybatis學習筆記(八)- 快取機制

工程目錄

image

1. 概述

  • MyBatis 包含一個非常強大的查詢快取特性,它可以非 常方便地配置和定製。快取可以極大的提升查詢效率。
  • MyBatis系統中預設定義了兩級快取。
    • 一級快取和二級快取。
      • 預設情況下,只有一級快取(SqlSession級別的快取, 也稱為本地快取)開啟。
      • 二級快取需要手動開啟和配置,他是基於namespace級 別的快取。
      • 為了提高擴充套件性。MyBatis定義了快取介面Cache。我們 可以通過實現Cache介面來自定義二級快取

2. 一級快取

2.1. 一級快取的體驗

2.1.1. 概述

  • 一級快取:(本地快取):
    • sqlSession級別的快取。一級快取是一直開啟的;
    • SqlSession級別的一個Map
    • 與資料庫同一次會話期間查詢到的資料會放在本地快取中。
      以後如果需要獲取相同的資料,直接從快取中拿,沒必要再去查詢資料庫;

2.1.2. 測試

@Test
	public void testFirstLevelCache() throws IOException{
		SqlSessionFactory sqlSessionFactory =
getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(1); System.out.println(emp01); //xxxxx Employee emp01 = mapper.getEmpById(1); System.
out.println(emp02); System.out.println(emp01==emp02); }finally{ openSession.close(); } }

2.1.3. 結果

image

2.2. 一級快取失效的四種情況

  • 一級快取失效情況(沒有使用到當前一級快取的情況,效果就是,還需要再向資料庫發出查詢):
    • sqlSession不同。
    • sqlSession相同,查詢條件不同.(當前一級快取中還沒有這個資料)
    • sqlSession相同,兩次查詢之間執行了增刪改操作(這次增刪改可能對當前資料有影響)
    • sqlSession相同,手動清除了一級快取(快取清空)openSession.clearCache()

3. 二級快取

3.1. 概述

  • 二級快取:(全域性快取):基於namespace級別的快取:一個namespace對應一個二級快取:
    • 工作機制:
      • 一個會話,查詢一條資料,這個資料就會被放在當前會話的一級快取中;
      • 如果會話關閉;一級快取中的資料會被儲存到二級快取中;新的會話查詢資訊,就可以參照二級快取中的內容;
      • sqlSession === EmployeeMapper ==> Employee |
        DepartmentMapper ===> Department
    • 不同namespace查出的資料會放在自己對應的快取中(map)
      • 效果:資料會從二級快取中獲取
        查出的資料都會被預設先放在一級快取中。

3.2. 使用

3.2.1. 概述

  1. 開啟全域性二級快取配置:
  2. 去mapper.xml中配置使用二級快取:
<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>
	<!--  
	eviction:快取的回收策略:
		• LRU – 最近最少使用的:移除最長時間不被使用的物件。
		• FIFO – 先進先出:按物件進入快取的順序來移除它們。
		• SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。
		• WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。
		• 預設的是 LRU。
	flushInterval:快取重新整理間隔
		快取多長時間清空一次,預設不清空,設定一個毫秒值
	readOnly:是否只讀:
		true:只讀;mybatis認為所有從快取中獲取資料的操作都是隻讀操作,不會修改資料。
				 mybatis為了加快獲取速度,直接就會將資料在快取中的引用交給使用者。不安全,速度快
		false:非只讀:mybatis覺得獲取的資料可能會被修改。
				mybatis會利用序列化&反序列的技術克隆一份新的資料給你。安全,速度慢
	size:快取存放多少元素;
	type="":指定自定義快取的全類名;
			實現Cache介面即可;
	-->
  1. 我們的 POJO 需要實現序列化介面
1. public class Department implements Serializable {
            .........
}
2. public class Employee implements Serializable{
            .........
}

3.2.2. 測試

    @Test
	public void testSecondLevelCache() throws IOException{
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		SqlSession openSession = sqlSessionFactory.openSession();
		SqlSession openSession2 = sqlSessionFactory.openSession();
		try{
			//1、
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
			
			Employee emp01 = mapper.getEmpById(1);
			System.out.println(emp01);
			openSession.close();
			
			//第二次查詢是從二級快取中拿到的資料,並沒有傳送新的sql
			Employee emp02 = mapper2.getEmpById(1);
			System.out.println(emp02);
			openSession2.close();
			
		}finally{
			
		}
	}

3.2.3. 結果

image

4. 快取有關的設定以及屬性

  • 和快取有關的設定/屬性:
    • cacheEnabled=true:false:關閉快取(二級快取關閉)(一級快取一直可用的)
    • 每個select標籤都有useCache=“true”:
      • false:不使用快取(一級快取依然使用,二級快取不使用)
    • 【每個增刪改標籤的:flushCache=“true”:(一級二級都會清除)】
      • 增刪改執行完成後就會清楚快取;
      • 測試:flushCache=“true”:一級快取就清空了;二級也會被清除;
      • 查詢標籤:flushCache=“false”: - 如果flushCache=true;每次查詢之後都會清空快取;快取是沒有被使用的;
    • sqlSession.clearCache();只是清除當前session的一級快取
    • localCacheScope:本地快取作用域:(一級快取SESSION);當前會話的所有資料儲存在會話快取中; STATEMENT:可以禁用一級快取;

5. 快取原理示意圖

image

6. 第三方快取整合

6.1. 步驟

  1. 匯入第三方快取包即可;
    • ehcache-core-2.6.8.jar
    • slf4j-api-1.6.1.jar
    • slf4j-log4j12-1.6.2.jar
  2. 匯入與第三方快取整合的適配包;官方有;
    • mybatis-ehcache-1.0.3.jar
  3. mapper.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(先進先出)
 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

6.1. 示意圖

image