1. 程式人生 > >Mybatis的一、二級快取

Mybatis的一、二級快取

 

MyBatis快取介紹

  Mybatis和Hibernate一樣,也有一級和二級快取,同樣預設開啟的只有一級快取,二級快取也需要手動配置開啟。

       Mybatis 提供了快取機制減輕資料庫壓力,提高資料庫效能

  1. 一級快取: 基於PerpetualCache 的 HashMap本地快取,其儲存作用域為 Session,當 Session flush  close 之後,該Session中的所有 Cache 就將清空
  2. 二級快取與一級快取其機制相同,預設也是採用 PerpetualCache,HashMap儲存,不同在於其儲存作用域為 Mapper(Namespace)
    ,並且可自定義儲存源,如 Ehcache。
  3. 對於快取資料更新機制,當某一個作用域(一級快取Session/二級快取Namespaces)的進行了 C/U/D 操作後,預設該作用域下所有 select 中的快取將被clear。

一、一級快取(預設是開啟的)

一級快取是SqlSession級別的快取,快取的資料只在SqlSession內有效。

每個與資料庫的連結SqlSession會話都有各自自己的快取,這些一級快取之間是不能通訊的,是相互獨立的快取空間!

  1)必須是同一個SqlSession會話, 發起一條sql語句

                SqlSession session = sqlSessionFactory.openSession();
		
		try {
			UserMapper userMapper = session.getMapper(UserMapper.class);
			
			User user = userMapper.getUser(1);
			System.out.println(user.getUsername());
			User user2 = userMapper.getUser(1);
			System.out.println(user2.getUsername());
			
		} finally {
			session.close();
		}

  2SqlSession清理快取, 發起一兩sql語句

    同一個sqlsession,查詢相同id的user,查詢中間,做了SqlSession清理快取,或者增改刪操作,都會發起兩條sql語句,

    用不同的sqlsession,查詢同一個id的user,也會發起兩條sql語句。

			User user = userMapper.getUser(1);
			System.out.println(user.getUsername());
			session.clearCache();
			User user2 = userMapper.getUser(1);
			System.out.println(user2.getUsername());

在操作資料庫的時候需要先建立SqlSession會話物件,在物件中有一個HashMap用於儲存快取資料,此HashMap是當前會話物件私有的,別的SqlSession會話物件無法訪問。

具體流程:

      1.第一次執行select完畢會將查到的資料寫入SqlSession內的HashMap中快取起來

      2.第二次執行select會從快取中查資料,如果select相同切傳引數一樣,那麼就能從快取中返回資料,不用去資料庫了,從而提高了效率

注意事項:

      1.如果SqlSession執行了DML操作(insert、update、delete),並commit了,那麼mybatis就會清空當前SqlSession快取中的所有快取資料,這樣可以保證快取中的存的資料永遠和資料庫中一致,避免出現髒讀

      2.當一個SqlSession結束後那麼他裡面的一級快取也就不存在了,mybatis預設是開啟一級快取,不需要配置

      3.mybatis的快取是基於[namespace:sql語句:引數]來進行快取的,意思就是,SqlSession的HashMap儲存快取資料時,是使用[namespace:sql:引數]作為key,查詢返回的語句作為value儲存的。

 

二、二級快取(需要手動配置開啟)

 

1.二級快取是mapper級別的快取,同一個namespace公用這一個二級快取,所以對SqlSession是共享的。

2.一級快取的生命週期隨著一次會話session的關閉而清空,開啟二級快取的情況下,一級快取裡的資料,在清空或者提交之前會轉存到二級快取的空間中繼續存在。

3.當一次會話sqlsession的快取裡如果存放著兩個不同型別的物件,比如User和Role物件,當一級快取清空之前,開起二級快取的情況下,它們兩個物件會分別存入各自的名稱空間的二級快取空間中;在二級快取中兩個物件是分別放在兩個獨立的Map物件裡的(各自的快取空間裡)。

開啟二級快取步驟:

1、全域性配置檔案中開啟二級快取

	<settings>
		<!-- 開啟二級快取 -->
		<setting name="cacheEnabled" value="true"/>
	</settings>	

2、在sql對映檔案中新增一個標籤<cache/>, 即開啟了這個namespace檔案的二級快取

<mapper namespace="cn.jq.mybatis.dao.UserMapper">
	<!-- 開啟二級快取  -->	
	<cache 
		eviction="FIFO"  
		flushInterval="60000" 
		size="512" 
		readOnly="true" /> 

<cache/>這個標籤中有關的屬性:

eviction可用的收回策略有:

  • LRU(預設值) – 最近最少使用的:移除最長時間不被使用的物件。
  • FIFO – 先進先出:按物件進入快取的順序來移除它們。
  • SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。
  • WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。

flushInterval(重新整理間隔)

可以被設定為任意的正整數,而且它們代表一個合理的毫秒 形式的時間段。預設情況是不設定,也

就是沒有重新整理間隔,快取僅僅呼叫語句時重新整理。

size(引用數目,預設值1024)
可以被設定為任意正整數,要記住你快取的物件數目和你執行環境的 可用記憶體資源數目。。

readOnly(只讀)屬性可以被設定為 true 或 false(預設)。

只讀的快取會給所有呼叫者返回緩 存物件的相同例項。因此這些物件不能被修改。這提供了很重

要的效能優勢。可讀寫的快取 會返回快取物件的拷貝(通過序列化) 。

3、Mybatis的二級快取使用的序列化介面,所以,POJO類就必須實現序列化介面

public class User implements Serializable{

	private static final long serialVersionUID = 1L;

測試:發起一條sql語句,

			SqlSession session = sqlSessionFactory.openSession();
			UserMapper userMapper = session.getMapper(UserMapper.class);
			User user = userMapper.getUser(1);
			System.out.println(user.getUsername());
			session.close(); //第一個會話關閉之前,清空一級快取資料,同時轉存到二級快取
			
			SqlSession session2 = sqlSessionFactory.openSession();
			UserMapper userMapper2 = session2.getMapper(UserMapper.class);
			User user2 = userMapper2.getUser(1);
			System.out.println(user2.getUsername());
			session2.close();

具體流程:

      1.當一個sqlseesion執行了一次select後,在關閉此session的時候,會將查詢結果快取到二級快取

      2.當另一個sqlsession執行select時,首先會在他自己的一級快取中找,如果沒找到,就回去二級快取中找,找到了就返回,就不用去資料庫了,從而減少了資料庫壓力提高了效能 

注意事項:

      1.如果SqlSession執行了DML操作(insert、update、delete),並commit了,那麼mybatis就會清空當前mapper快取中的所有快取資料,這樣可以保證快取中的存的資料永遠和資料庫中一致,避免出現髒讀

      2.mybatis的快取是基於[namespace:sql語句:引數]來進行快取的,意思就是,SqlSession的HashMap儲存快取資料時,是使用[namespace:sql:引數]作為key,查詢返回的語句作為value儲存的。

 

總結:

1.全域性變數配置cacheEnabled

ture(預設):開啟二級快取,

false:關閉二級快取,但一級快取不受影響

2.對映檔案中mapper標籤下<cache/>

配置有:開啟二級快取

沒配置有:關閉二級快取,一級快取不受影響

3.每個select標籤都可以設定 useCache 屬性:

true(預設):上面1和2開啟二級快取後,二級快取生效

false:哪怕上面1和2開啟了二級快取,二級快取在這個select也會失效,

一級快取不受影響

4.增改刪查標籤都可以設定flushCache屬性:

增改刪true(預設):執行增改刪操作後,重新整理快取,把原來的快取幹掉,

注意這個設定有點特殊,幹掉的快取包括一、二級快取

查false(預設):如果在查詢標籤上把它設定為true,等於禁用所有快取

5.全部變數 localCacheScope(瞭解):

SESSION(預設)開啟一級快取

STATEMENT:如果設定為這裡,相當於關閉一級快取