1.MyBatis緩存 MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定製.緩存可以極大的提升查詢效率. 1).一級緩存 public Employee getEmpById(Integer id); <select id="getEmpById" resultType="c ...
1.MyBatis緩存
MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定製.緩存可以極大的提升查詢效率.
1).一級緩存
public Employee getEmpById(Integer id);
<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql" > select * from tbl_employee where id = #{id} </select>
@Test public void testFirstLevelCache() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(10); System.out.println(emp01); // Employee emp02 = mapper.getEmpById(1-0); System.out.println(emp02); System.out.println(emp01==emp02); }finally { openSession.close(); } }
2).一級緩存失效情況
(1).sqlSession不同
(2).sqlSession相同,查詢條件不同(當前一級緩存中還沒有這個數據)
(3).sqlSession相同,兩次查詢之間執行了增刪改操作(這次增刪改可能對當前數據有影響)
(4).sqlSession相同,手動清除了一級緩存
public Employee getEmpById(Integer id);
<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql" > select * from tbl_employee where id = #{id} </select>
@Test public void testFirstLevelCache() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(10); System.out.println(emp01); //1、Sqlsession不同 // SqlSession openSession2 = sqlSessionFactory.openSession(); // EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class); // Employee emp02 = mapper2.getEmpById(10); //2、sqlSession相同,查詢條件不同 // Employee emp02 = mapper.getEmpById(3); // System.out.println(emp02); // System.out.println(emp01==emp02); //3、sqlSession相同,兩次查詢之間執行了增刪改操作 // mapper.addEmp(new Employee(null, "testCache", "[email protected]", "1")); // System.out.println("數據添加成功"); // Employee emp02 = mapper.getEmpById(10); // System.out.println(emp02); // System.out.println(emp01==emp02); //4、sqlSession相同,手動清除了一級緩存 openSession.clearCache(); Employee emp02 = mapper.getEmpById(10); System.out.println(emp02); System.out.println(emp01==emp02); }finally { openSession.close(); } }
3).二級緩存
二級緩存(second level cache),全局作用域緩存.
二級緩存預設不開啟,需要手動配置.
MyBatis提供二級緩存的介面以及實現,緩存實現要求POJO實現Serializable介面.
二級緩存在 SqlSession 關閉或提交之後才會生效.
(1).二級緩存使用
二級緩存使用:
①.開啟全局二級緩存配置:<setting name="cacheEnabled" value="true"/>
②.去需要使用二級緩存的xml中配置使用二級緩存;添加<cache></cache>
③.POJO需要實現序列化介面
<setting name="cacheEnabled" value="true"/>
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper"> <!-- cache:使用二級緩存的namespace --> <!-- eviction:緩存的清除策略;LRU|FIFO|SOFT|WEAK --> <!-- LRU – 最近最少使用的:移除最長時間不被使用的對象。 --> <!-- FIFO – 先進先出:按對象進入緩存的順序來移除它們。 --> <!-- SOFT – 軟引用:基於垃圾回收器狀態和軟引用規則移除對象。 --> <!-- WEAK – 弱引用:更積極地基於垃圾收集器狀態和弱引用規則移除對象。 --> <!-- flushInterval(刷新間隔):緩存多長時間清空一次,預設不清空,可以設置一個毫秒值啟用刷新間隔 --> <!-- readOnly(只讀):屬性可以被設置為 true 或 false --> <!-- true:只讀;mybatis認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據; --> <!-- 只讀的緩存會給所有調用者返回緩存對象的相同實例。 因此這些對象不能被修改。 提供了可觀的性能提升--> <!-- false:非只讀;mybatis覺得獲取的數據可能會被修改; --> <!-- 可讀寫的緩存會(通過序列化)返回緩存對象的拷貝。 速度上會慢一些,但是更安全,因此預設值是 false --> <!-- size(引用數目):屬性可以被設置為任意正整數,要註意欲緩存對象的大小和運行環境中可用的記憶體資源.預設值是 1024 --> <!-- type:屬性指定的類必須實現 org.apache.ibatis.cache.Cache 介面.且提供一個接受 String 參數作為 id 的構造器 --> <!-- 指定自定義緩存的全類名,實現Cache介面即可 --> <!-- <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache> --> <cache></cache> </mapper>
@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 //mapper2.addEmp(new Employee(null, "aaa", "nnn", "0")); Employee emp02 = mapper2.getEmpById(1); System.out.println(emp02); openSession2.close(); }finally { } }
(2).二級緩存工作原理
二級緩存工作原理:
①.一個會話,查詢一條數,這個數據就會被放在當前會話的一級緩存中;
②.如果會話關閉;一級緩存中的數據會被保存到二級緩存中;新的會話查詢信息,就可以參照二級緩存中的內容;
③.不同namespace查出的數據會放在自己對應的緩存中(map):sqlSession===EmployeeMapper==>Employee|DepartmentMapper===>Department
④.二級緩存工作效果:查出的數據都會被預設先放在一級緩存中.只有會話提交或者關閉以後,一級緩存中的數據才會轉移到二級緩存中;
(3).二級緩存屬性設置
①.cacheEnabled="true|false": false關閉緩存(二級緩存關閉)(一級緩存一直可用的)
②.每個select標簽都有useCache="true|false": false不使用緩存(一級緩存依然使用,二級緩存不使用)
③.*每個增刪改標簽的:flushCache="true|false":(一級二級都會清除)增刪改執行完成後就會清楚緩存;
測試:flushCache="true":一級緩存會被清空;二級也會被清空;每次查詢之後都會清空緩存,緩存是沒有被使用的;
④.sqlSession.clearCache();只是清除當前session的一級緩存
⑤.localCacheScope:本地緩存作用域;一級緩存SESSION;當前會話的所有數據保存在會話緩存中;STATEMENT:可以禁用一級緩存;
/** * MyBatis系統中預設定義了兩級緩存:一級緩存和二級緩存 * 一級緩存(本地緩存):sqlSession級別的緩存;一級緩存是一直開啟的;SqlSession級別的一個Map * 與資料庫同一次會話期間查詢到的數據會放在本地緩存中; * 以後如果需要獲取相同的數據,直接從緩存中拿,沒必要再去查詢資料庫; * 一級緩存失效情況:沒有使用到一級緩存的情況,效果就是兩次查詢都需要向資料庫發出查詢 * 1、sqlSession不同 * 2、sqlSession相同,查詢條件不同(當前一級緩存中還沒有這個數據) * 3、sqlSession相同,兩次查詢之間執行了增刪改操作(這次增刪改可能對當前數據有影響) * 4、sqlSession相同,手動清除了一級緩存 * * 二級緩存(全局緩存):基於namespace級別的緩存;一個namespace對應一個二級緩存; * 二級緩存工作原理: * 1、一個會話,查詢一條數,這個數據就會被放在當前會話的一級緩存中; * 2、如果會話關閉;一級緩存中的數據會被保存到二級緩存中;新的會話查詢信息,就可以參照二級緩存中的內容; * 3、不同namespace查出的數據會放在自己對應的緩存中(map):sqlSession===EmployeeMapper==>Employee|DepartmentMapper===>Department * 二級緩存工作效果:查出的數據都會被預設先放在一級緩存中.只有會話提交或者關閉以後,一級緩存中的數據才會轉移到二級緩存中; * 二級緩存使用: * 1、開啟全局二級緩存配置:<setting name="cacheEnabled" value="true"/> * 2、去需要使用二級緩存的xml中配置使用二級緩存;添加<cache></cache> * 3、POJO需要實現序列化介面 * * 緩存有關屬性/設置: * 1、cacheEnabled="true|false": false關閉緩存(二級緩存關閉)(一級緩存一直可用的) * 2、每個select標簽都有useCache="true|false": false不使用緩存(一級緩存依然使用,二級緩存不使用) * 3、*每個增刪改標簽的:flushCache="true|false":(一級二級都會清除)增刪改執行完成後就會清楚緩存; * 測試:flushCache="true":一級緩存會被清空;二級也會被清空;每次查詢之後都會清空緩存,緩存是沒有被使用的; * 4、sqlSession.clearCache();只是清除當前session的一級緩存 * 5、localCacheScope:本地緩存作用域;一級緩存SESSION;當前會話的所有數據保存在會話緩存中;STATEMENT:可以禁用一級緩存; * @throws IOException */ |
2.第三方緩存整合
EhCache 是一個純Java的進程內緩存框架,具有快速、精幹等特點,是Hibernate中預設的CacheProvider.
MyBatis定義了Cache介面方便我們進行自定義擴展.
參考文檔:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache
http://mybatis.org/ehcache-cache/index.html