深入理解mybatis原理(六) MyBatis緩存機制的設計與實現如何細粒度地控制你的MyBatis二級緩存

  前幾天網友chanfish 給我拋出了一個問題,籠統地講就是如何能細粒度地控制MyBatis的二級緩存問題,醞釀了幾天,覺得可以寫個插件來實現這個這一功能。本文就是從問題入手,一步步分析現存的MyBatis的二級緩存的不足之處,探討一點可以改進的地方,並且對不足之處開發一個插件進行彌補。

本文如下組織結構:

  1. 一個關於MyBatis的二級緩存的實際問題
  2. 當前MyBatis二級緩存的工作機制
  3. mybatis-enhanced-cache插件的設計和工作原理
  4. mybatis-enhanced-cache 插件的使用實例

1.一個關於MyBatis的二級緩存的實際問題

網友chanfish 給我拋出的問題

現有AMapper.xml中定義了對數據庫ATable 的CRUD操作,BMapper定義了對數據庫BTable的CRUD操作;
假設 MyBatis 的二級緩存開啓,並且 AMapper 中使用了二級緩存,AMapper對應的二級緩存爲ACache
除此之外,AMapper 中還定義了一個跟BTable有關的查詢語句,類似如下所述:

[html] view plain copy
 
在CODE上查看代碼片派生到我的代碼片在CODE上查看代碼片派生到我的代碼片
  1. <select id="selectATableWithJoin" resultMap="BaseResultMap" useCache="true">  
  2.       select * from ATable left join BTable on ....  
  3. </select>  
[html] view plain copy
  1. <select id="selectATableWithJoin" resultMap="BaseResultMap" useCache="true">  
  2.       select * from ATable left join BTable on ....  
  3. </select>  

執行以下操作:

1. 執行AMapper中的"selectATableWithJoin" 操作,此時會將查詢到的結果放置到AMapper對應的二級緩存ACache中;

2. 執行BMapper中對BTable的更新操作(update、delete、insert)後,BTable的數據更新;

3. 再執行1完全相同的查詢,這時候會直接從AMapper二級緩存ACache中取值,將ACache中的值直接返回;


好,問題就出現在第3步上:

     由於AMapper的“selectATableWithJoin” 對應的SQL語句需要和BTable進行join查找,而在第 2 步BTable的數據已經更新了,但是第 3 步查詢的值是第 1 步的緩存值,已經極有可能跟真實數據庫結果不一樣,即ACache中緩存數據過期了!


總結來看,就是:

         對於某些使用了 join連接的查詢,如果其關聯的表數據發生了更新,join連接的查詢由於先前緩存的原因,導致查詢結果和真實數據不同步;

從MyBatis的角度來看,這個問題可以這樣表述:

        對於某些表執行了更新(update、delete、insert)操作後,如何去清空跟這些表有關聯的查詢語句所造成的緩存;


當前的MyBatis的緩存機制不能很好地處理這一問題,下面我們將從當前的MyBatis的緩存機制入手,分析這一問題:


2. 當前MyBatis二級緩存的工作機制:

當前MyBatis二級緩存的工作機制:

MyBatis二級緩存的一個重要特點:即鬆散的Cache緩存管理和維護。

     一個Mapper中定義的增刪改查操作只能影響到自己關聯的Cache對象。如上圖所示的Mapper namespace1中定義的若干CRUD語句,產生的緩存只會被放置到相應關聯的Cache1中,即Mapper namespace2,namespace3,namespace4 中的CRUD的語句不會影響到Cache1。

     可以看出,Mapper之間的緩存關係比較鬆散,相互關聯的程度比較弱。

     

     現在再回到上面描述的問題,如果我們將AMapper和BMapper共用一個Cache對象,那麼,當BMapper執行更新操作時,可以清空對應Cache中的所有的緩存數據,這樣的話,數據不是也可以保持最新嗎?

    確實這個也是一種解決方案,不過,它會使緩存的使用效率變的很低!AMapper和BMapper的任意的更新操作都會將共用的Cache清空,會頻繁地清空Cache,導致Cache實際的命中率和使用率就變得很低了,所以這種策略實際情況下是不可取的。


     最理想的解決方案就是:

          對於某些表執行了更新(update、delete、insert)操作後,如何去清空跟這些表有關聯的查詢語句所造成的緩存;

     這樣,就是以很細的粒度管理MyBatis內部的緩存,使得緩存的使用率和準確率都能大大地提升。   

    基於這個思路,我寫了一個對應的mybatis-enhanced-cache 緩存插件,可以很好地支持上述的功能。  

    對於上述的例子中,該插件可以實現:當BMapper對BTable執行了更新操作時,指定清除與BTable相關聯的selectATableWithJoin查詢語句在ACache中產生的緩存。

     

     接下來就來看看這個mybatis-enhanced-cache插件的設計原理吧:



3.mybatis-enhanced-cache插件的設計和工作原理


mybatis-enhanced-cache插件的設計和工作原理

該插件主要由兩個構件組成:EnhancedCachingExecutorEnhancedCachingManager

EnhancedCachingExecutor是針對於Executor的攔截器,攔截Executor的幾個關鍵的方法;

EnhancedCachingExecutor主要做以下幾件事:

1. 每當有Executor執行query操作時,

       1.1  記錄下該查詢StatementId和CacheKey,然後將其添加到EnhancedCachingManager中;

       1.2  記錄下該查詢StatementId 和此StatementId所屬Mapper內的Cache緩存對象引用,添加到EnhancedCachingManager中;

2. 每當Executor執行了update操作時,將此 update操作的StatementId傳遞給EnhancedCachingManager,讓EnhancedCachingManager根據此update的StatementId的配置,去清空指定的查詢語句所產生的緩存;


另一個構件:EnhancedCachingManager,它也是本插件的核心,它維護着以下幾樣東西:

1. 整個MyBatis的所有查詢所產生的CacheKey集合(以statementId分類);

2. 所有的使用過了的查詢的statementId 及其對應的Cache緩存對象的引用;

3. update類型的StatementId和查詢StatementId集合的映射,用於當Update類型的語句執行時,根據此映射決定應該清空哪些查詢語句產生的緩存;

如下圖所示:


工作原理:

           原理很簡單,就是 當執行了某個update操作時,根據配置信息去清空指定的查詢語句在Cache中所產生的緩存數據。



如何獲取mybatis-enhanced-cache插件源碼

1. 源碼和jar包2合一壓縮包

2. github 地址,直接fork即可:

         https://github.com/LuanLouis/mybatis-enhanced-cache



4. mybatis-enhanced-cache 插件的使用實例:

1. 下載 mybatis-enhanced-cache.rar壓縮包,解壓,將其內的mybatis-enhanced-cache-0.0.1-SNAPSHOT.jar添加到項目的classpath下;


2. 配置MyBatis配置文件如下:

[html] view plain copy
 
在CODE上查看代碼片派生到我的代碼片在CODE上查看代碼片派生到我的代碼片
  1. <plugins>  
  2.      <plugin interceptor="org.luanlouis.mybatis.plugin.cache.EnhancedCachingExecutor">  
  3.         <property name="dependency" value="dependencys.xml"/>  
  4.         <property name="cacheEnabled" value="true"/>  
  5.      </plugin>  
  6. </plugins>  
[html] view plain copy
  1. <plugins>  
  2.      <plugin interceptor="org.luanlouis.mybatis.plugin.cache.EnhancedCachingExecutor">  
  3.         <property name="dependency" value="dependencys.xml"/>  
  4.         <property name="cacheEnabled" value="true"/>  
  5.      </plugin>  
  6. </plugins>  

    其中,<property name="dependency"> 中的value屬性是 StatementId之間的依賴關係的配置文件路徑。


3. 配置StatementId之間的依賴關係

[html] view plain copy
 
在CODE上查看代碼片派生到我的代碼片在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <dependencies>  
  3.    <statements>  
  4.        <statement id="com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey">  
  5.           <observer id="com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments" />  
  6.        </statement>  
  7.    </statements>  
  8. </dependencies>  
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <dependencies>  
  3.    <statements>  
  4.        <statement id="com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey">  
  5.           <observer id="com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments" />  
  6.        </statement>  
  7.    </statements>  
  8. </dependencies>  

 <statement>節點配置的是更新語句的statementId,其內的子節點<observer> 配置的是當更新語句執行後,應當清空緩存的查詢語句的StatementId。子節點<observer>可以有多個。

 如上的配置,則說明,如果"com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey" 更新語句執行後,由 “com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments” 語句所產生的放置在Cache緩存中的數據都都會被清空。


4. 配置DepartmentsMapper.xml 和EmployeesMapper.xml

[html] view plain copy
 
在CODE上查看代碼片派生到我的代碼片在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >  
  3. <mapper namespace="com.louis.mybatis.dao.DepartmentsMapper" >  
  4.      
  5.    <cache></cache>  
  6.   
  7.   <resultMap id="BaseResultMap" type="com.louis.mybatis.model.Department" >  
  8.     <id column="DEPARTMENT_ID" property="departmentId" jdbcType="DECIMAL" />  
  9.     <result column="DEPARTMENT_NAME" property="departmentName" jdbcType="VARCHAR" />  
  10.     <result column="MANAGER_ID" property="managerId" jdbcType="DECIMAL" />  
  11.     <result column="LOCATION_ID" property="locationId" jdbcType="DECIMAL" />  
  12.   </resultMap>  
  13.     
  14.     
  15.   <sql id="Base_Column_List" >  
  16.     DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID  
  17.   </sql>  
  18.     
  19.   <update id="updateByPrimaryKey" parameterType="com.louis.mybatis.model.Department" >  
  20.     update HR.DEPARTMENTS  
  21.     set DEPARTMENT_NAME = #{departmentName,jdbcType=VARCHAR},  
  22.       MANAGER_ID = #{managerId,jdbcType=DECIMAL},  
  23.       LOCATION_ID = #{locationId,jdbcType=DECIMAL}  
  24.     where DEPARTMENT_ID = #{departmentId,jdbcType=DECIMAL}  
  25.   </update>  
  26.     <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >  
  27.     select   
  28.     <include refid="Base_Column_List" />  
  29.     from HR.DEPARTMENTS  
  30.     where DEPARTMENT_ID = #{departmentId,jdbcType=DECIMAL}  
  31.   </select>  
  32. </mapper>  
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >  
  3. <mapper namespace="com.louis.mybatis.dao.DepartmentsMapper" >  
  4.      
  5.    <cache></cache>  
  6.   
  7.   <resultMap id="BaseResultMap" type="com.louis.mybatis.model.Department" >  
  8.     <id column="DEPARTMENT_ID" property="departmentId" jdbcType="DECIMAL" />  
  9.     <result column="DEPARTMENT_NAME" property="departmentName" jdbcType="VARCHAR" />  
  10.     <result column="MANAGER_ID" property="managerId" jdbcType="DECIMAL" />  
  11.     <result column="LOCATION_ID" property="locationId" jdbcType="DECIMAL" />  
  12.   </resultMap>  
  13.     
  14.     
  15.   <sql id="Base_Column_List" >  
  16.     DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID  
  17.   </sql>  
  18.     
  19.   <update id="updateByPrimaryKey" parameterType="com.louis.mybatis.model.Department" >  
  20.     update HR.DEPARTMENTS  
  21.     set DEPARTMENT_NAME = #{departmentName,jdbcType=VARCHAR},  
  22.       MANAGER_ID = #{managerId,jdbcType=DECIMAL},  
  23.       LOCATION_ID = #{locationId,jdbcType=DECIMAL}  
  24.     where DEPARTMENT_ID = #{departmentId,jdbcType=DECIMAL}  
  25.   </update>  
  26.     <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >  
  27.     select   
  28.     <include refid="Base_Column_List" />  
  29.     from HR.DEPARTMENTS  
  30.     where DEPARTMENT_ID = #{departmentId,jdbcType=DECIMAL}  
  31.   </select>  
  32. </mapper>  
[html] view plain copy
 
在CODE上查看代碼片派生到我的代碼片在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  3. <mapper namespace="com.louis.mybatis.dao.EmployeesMapper">  
  4.   
  5.   <cache eviction="LRU" flushInterval="100000" size="10000"/>  
  6.   
  7.   <resultMap id="BaseResultMap" type="com.louis.mybatis.model.Employee">  
  8.     <id column="EMPLOYEE_ID" jdbcType="DECIMAL" property="employeeId" />  
  9.     <result column="FIRST_NAME" jdbcType="VARCHAR" property="firstName" />  
  10.     <result column="LAST_NAME" jdbcType="VARCHAR" property="lastName" />  
  11.     <result column="EMAIL" jdbcType="VARCHAR" property="email" />  
  12.     <result column="PHONE_NUMBER" jdbcType="VARCHAR" property="phoneNumber" />  
  13.     <result column="HIRE_DATE" jdbcType="DATE" property="hireDate" />  
  14.     <result column="JOB_ID" jdbcType="VARCHAR" property="jobId" />  
  15.     <result column="SALARY" jdbcType="DECIMAL" property="salary" />  
  16.     <result column="COMMISSION_PCT" jdbcType="DECIMAL" property="commissionPct" />  
  17.     <result column="MANAGER_ID" jdbcType="DECIMAL" property="managerId" />  
  18.     <result column="DEPARTMENT_ID" jdbcType="DECIMAL" property="departmentId" />  
  19.   </resultMap>  
  20.   
  21.   <sql id="Base_Column_List">  
  22.     EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER, HIRE_DATE, JOB_ID, SALARY,   
  23.     COMMISSION_PCT, MANAGER_ID, DEPARTMENT_ID  
  24.   </sql>  
  25.     
  26.   <select id="selectWithDepartments" parameterType="java.lang.Integer" resultMap="BaseResultMap" useCache="true" >  
  27.     select   
  28.     *  
  29.     from HR.EMPLOYEES t left join HR.DEPARTMENTS S ON T.DEPARTMENT_ID = S.DEPARTMENT_ID  
  30.     where EMPLOYEE_ID = #{employeeId,jdbcType=DECIMAL}  
  31.   </select>  
  32.     
  33. </mapper>  
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  3. <mapper namespace="com.louis.mybatis.dao.EmployeesMapper">  
  4.   
  5.   <cache eviction="LRU" flushInterval="100000" size="10000"/>  
  6.   
  7.   <resultMap id="BaseResultMap" type="com.louis.mybatis.model.Employee">  
  8.     <id column="EMPLOYEE_ID" jdbcType="DECIMAL" property="employeeId" />  
  9.     <result column="FIRST_NAME" jdbcType="VARCHAR" property="firstName" />  
  10.     <result column="LAST_NAME" jdbcType="VARCHAR" property="lastName" />  
  11.     <result column="EMAIL" jdbcType="VARCHAR" property="email" />  
  12.     <result column="PHONE_NUMBER" jdbcType="VARCHAR" property="phoneNumber" />  
  13.     <result column="HIRE_DATE" jdbcType="DATE" property="hireDate" />  
  14.     <result column="JOB_ID" jdbcType="VARCHAR" property="jobId" />  
  15.     <result column="SALARY" jdbcType="DECIMAL" property="salary" />  
  16.     <result column="COMMISSION_PCT" jdbcType="DECIMAL" property="commissionPct" />  
  17.     <result column="MANAGER_ID" jdbcType="DECIMAL" property="managerId" />  
  18.     <result column="DEPARTMENT_ID" jdbcType="DECIMAL" property="departmentId" />  
  19.   </resultMap>  
  20.   
  21.   <sql id="Base_Column_List">  
  22.     EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER, HIRE_DATE, JOB_ID, SALARY,   
  23.     COMMISSION_PCT, MANAGER_ID, DEPARTMENT_ID  
  24.   </sql>  
  25.     
  26.   <select id="selectWithDepartments" parameterType="java.lang.Integer" resultMap="BaseResultMap" useCache="true" >  
  27.     select   
  28.     *  
  29.     from HR.EMPLOYEES t left join HR.DEPARTMENTS S ON T.DEPARTMENT_ID = S.DEPARTMENT_ID  
  30.     where EMPLOYEE_ID = #{employeeId,jdbcType=DECIMAL}  
  31.   </select>  
  32.     
  33. </mapper>  


5. 測試代碼:

[java] view plain copy
 
在CODE上查看代碼片派生到我的代碼片在CODE上查看代碼片派生到我的代碼片
  1. package com.louis.mybatis.test;  
  2.   
  3. import java.io.InputStream;  
  4. import java.util.Date;  
  5. import java.util.HashMap;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9.   
  10. import org.apache.ibatis.io.Resources;  
  11. import org.apache.ibatis.session.SqlSession;  
  12. import org.apache.ibatis.session.SqlSessionFactory;  
  13. import org.apache.ibatis.session.SqlSessionFactoryBuilder;  
  14. import org.apache.log4j.Logger;  
  15.   
  16. import com.louis.mybatis.model.Department;  
  17. import com.louis.mybatis.model.Employee;  
  18.   
  19. /** 
  20.  * SqlSession 簡單查詢演示類 
  21.  * @author louluan 
  22.  */  
  23. public class SelectDemo3 {  
  24.   
  25.     private static final Logger loger = Logger.getLogger(SelectDemo3.class);  
  26.       
  27.     public static void main(String[] args) throws Exception {  
  28.         InputStream inputStream = Resources.getResourceAsStream("mybatisConfig.xml");  
  29.         SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  
  30.         SqlSessionFactory factory = builder.build(inputStream);  
  31.           
  32.         SqlSession sqlSession = factory.openSession(true);  
  33.         SqlSession sqlSession2 = factory.openSession(true);  
  34.         //3.使用SqlSession查詢  
  35.         Map<String,Object> params = new HashMap<String,Object>();  
  36.         params.put("employeeId",10);  
  37.         //a.查詢工資低於10000的員工  
  38.         Date first = new Date();  
  39.         //第一次查詢  
  40.         List<Employee> result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  41.         sqlSession.commit();  
  42.         checkCacheStatus(sqlSession);  
  43.         params.put("employeeId"11);  
  44.         result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  45.         sqlSession.commit();  
  46.         checkCacheStatus(sqlSession);  
  47.         params.put("employeeId"12);  
  48.         result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  49.         sqlSession.commit();  
  50.         checkCacheStatus(sqlSession);  
  51.         params.put("employeeId"13);  
  52.         result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  53.         sqlSession.commit();  
  54.         checkCacheStatus(sqlSession);  
  55.         Department department = sqlSession.selectOne("com.louis.mybatis.dao.DepartmentsMapper.selectByPrimaryKey",10);  
  56.         department.setDepartmentName("updated");  
  57.         sqlSession2.update("com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey", department);  
  58.         sqlSession.commit();  
  59.         checkCacheStatus(sqlSession);  
  60.     }  
  61.       
  62.       
  63.     public static void checkCacheStatus(SqlSession sqlSession)  
  64.     {  
  65.         loger.info("------------Cache Status------------");  
  66.         Iterator<String> iter = sqlSession.getConfiguration().getCacheNames().iterator();  
  67.         while(iter.hasNext())  
  68.         {  
  69.             String it = iter.next();  
  70.             loger.info(it+":"+sqlSession.getConfiguration().getCache(it).getSize());  
  71.         }  
  72.         loger.info("------------------------------------");  
  73.           
  74.     }  
  75.   
  76. }  
[java] view plain copy
  1. package com.louis.mybatis.test;  
  2.   
  3. import java.io.InputStream;  
  4. import java.util.Date;  
  5. import java.util.HashMap;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9.   
  10. import org.apache.ibatis.io.Resources;  
  11. import org.apache.ibatis.session.SqlSession;  
  12. import org.apache.ibatis.session.SqlSessionFactory;  
  13. import org.apache.ibatis.session.SqlSessionFactoryBuilder;  
  14. import org.apache.log4j.Logger;  
  15.   
  16. import com.louis.mybatis.model.Department;  
  17. import com.louis.mybatis.model.Employee;  
  18.   
  19. /** 
  20.  * SqlSession 簡單查詢演示類 
  21.  * @author louluan 
  22.  */  
  23. public class SelectDemo3 {  
  24.   
  25.     private static final Logger loger = Logger.getLogger(SelectDemo3.class);  
  26.       
  27.     public static void main(String[] args) throws Exception {  
  28.         InputStream inputStream = Resources.getResourceAsStream("mybatisConfig.xml");  
  29.         SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  
  30.         SqlSessionFactory factory = builder.build(inputStream);  
  31.           
  32.         SqlSession sqlSession = factory.openSession(true);  
  33.         SqlSession sqlSession2 = factory.openSession(true);  
  34.         //3.使用SqlSession查詢  
  35.         Map<String,Object> params = new HashMap<String,Object>();  
  36.         params.put("employeeId",10);  
  37.         //a.查詢工資低於10000的員工  
  38.         Date first = new Date();  
  39.         //第一次查詢  
  40.         List<Employee> result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  41.         sqlSession.commit();  
  42.         checkCacheStatus(sqlSession);  
  43.         params.put("employeeId"11);  
  44.         result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  45.         sqlSession.commit();  
  46.         checkCacheStatus(sqlSession);  
  47.         params.put("employeeId"12);  
  48.         result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  49.         sqlSession.commit();  
  50.         checkCacheStatus(sqlSession);  
  51.         params.put("employeeId"13);  
  52.         result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);  
  53.         sqlSession.commit();  
  54.         checkCacheStatus(sqlSession);  
  55.         Department department = sqlSession.selectOne("com.louis.mybatis.dao.DepartmentsMapper.selectByPrimaryKey",10);  
  56.         department.setDepartmentName("updated");  
  57.         sqlSession2.update("com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey", department);  
  58.         sqlSession.commit();  
  59.         checkCacheStatus(sqlSession);  
  60.     }  
  61.       
  62.       
  63.     public static void checkCacheStatus(SqlSession sqlSession)  
  64.     {  
  65.         loger.info("------------Cache Status------------");  
  66.         Iterator<String> iter = sqlSession.getConfiguration().getCacheNames().iterator();  
  67.         while(iter.hasNext())  
  68.         {  
  69.             String it = iter.next();  
  70.             loger.info(it+":"+sqlSession.getConfiguration().getCache(it).getSize());  
  71.         }  
  72.         loger.info("------------------------------------");  
  73.           
  74.     }  
  75.   
  76. }  

結果輸出:

結果分析:

從上述的結果可以看出,前四次執行了“com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments”語句,EmployeesMapper對應的Cache緩存中存儲的結果緩存有1個增加到4個。

當執行了"com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey"後,EmployeeMapper對應的緩存Cache結果被清空了,即"com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey"更新語句引起了EmployeeMapper中的"com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments"緩存的清空。

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