浅谈MyBatis二级缓存
一、二級緩存介紹
我們知道MyBatis 提供了一級緩存來減輕數(shù)據(jù)庫的壓力,但是一級緩存是一個SqlSession(會話)級別的緩存,這也就意味著一級緩存的適用范圍比較小。在一級緩存的基礎(chǔ)上,MyBatis 提供了二級緩存機(jī)制,二級緩存是一個namespace級別的緩存,相對于一級緩存而言,二級緩存允許跨SqlSession工作,因此二級緩存的作用范圍更大。
有關(guān)一級緩存可參考博文:
https://blog.csdn.net/codejas/article/details/79545367
二、二級緩存運(yùn)行機(jī)制
每個SqlSession在執(zhí)行查詢操作的時候,都會將查詢的結(jié)果放在當(dāng)前會話的一級緩存中。如果當(dāng)前會話關(guān)閉,一級緩存中的數(shù)據(jù)會被保存在二級緩存中。因此二級緩存是在一級緩存的基礎(chǔ)上進(jìn)行擴(kuò)展的,不同的namespace查出的數(shù)據(jù)都會將數(shù)據(jù)存在自己對應(yīng)的緩存中,這些緩存信息使用Map存儲。
需要注意的地方是:MyBatis 在開啟二級緩存的情況下,如果發(fā)出了一條SQL 查詢語句,會先向二級緩存中查詢是否有對應(yīng)的緩存數(shù)據(jù),如果沒有再接著查詢一級緩存中的數(shù)據(jù),如果一級緩存中也沒有對應(yīng)的緩存數(shù)據(jù),才會向數(shù)據(jù)庫發(fā)送SQL。下面附一張蹩腳的二級緩存運(yùn)行機(jī)制圖。
三、實現(xiàn)二級緩存的步驟
1.在MyBatis 全局配置文件中開啟二級緩存的配置,默認(rèn)也是開啟的,建議自己設(shè)置為開啟的。
2.在對應(yīng)的SQL 映射文件中加入<cache/>標(biāo)簽。
3.將返回的JavaBean 數(shù)據(jù)類型的類實現(xiàn)Serializable(序列化)接口。
知道了二級緩存的實現(xiàn)方式,下面就來體會一下二級緩存帶來的作用。
四、二級緩存初體驗
MyBatis 全局配置文件:
<!-- 配置二級緩存,默認(rèn)也是開啟的,建議手動設(shè)置一下 --><setting name="cacheEnabled" value="true"/>POJO 實現(xiàn)序列化接口:
package com.jas.mybatis.bean;import java.io.Serializable;public class Department implements Serializable{private Integer id;private String departmentName;//省略get、set 與toString 方法 }mapper 接口:
Department getDeptById(Integer id);SQL 映射文件:
<!-- 在需要使用二級緩存的SQL 映射文件中添加 <cache/> 標(biāo)簽相關(guān)的一些參數(shù)介紹:eviction:緩存回收策略flushInterval:緩存刷新時間,單位是毫秒,默認(rèn)不刷新size:可存儲多少個緩存對象,只能是正整數(shù),合理的設(shè)置可以防止內(nèi)存泄漏readOnly:是否只讀--><cache/><select id="getDeptById" resultType="com.jas.mybatis.bean.Department">SELECT id, dept_name departmentName FROM t_dept WHERE id = #{id}</select>測試代碼:
// 用于返回SqlSessionFactory 對象private SqlSessionFactory getSqlSession() throws IOException {String resource = "mybatis-config.xml";InputStream is = Resources.getResourceAsStream(resource);return new SqlSessionFactoryBuilder().build(is); }@Testpublic void secondLevelTest() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSession();//創(chuàng)建兩個不同的會話SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();DepatmentMapper depatmentMapper1 = sqlSession1.getMapper(DepatmentMapper.class);DepatmentMapper depatmentMapper2 = sqlSession2.getMapper(DepatmentMapper.class);Department department1 = depatmentMapper1.getDeptById(1);System.out.println(department1); // 關(guān)閉當(dāng)前的會話1, 否則二級緩存不起作用sqlSession1.close();Department department2 = depatmentMapper2.getDeptById(1);System.out.println(department2);// 關(guān)閉會話2sqlSession2.close();}測試結(jié)果:
當(dāng)會話1 查詢結(jié)束并關(guān)閉后,我們使用另一個會話執(zhí)行與會話1 相同的SQL 查詢語句,發(fā)現(xiàn)并沒有發(fā)送SQL 語句,因為緩存中已經(jīng)保存了要查詢的數(shù)據(jù),這次直接從緩存中獲取數(shù)據(jù),這就是MyBatis 提供的跨會話級別(SqlSession)的二級緩存機(jī)制。
五、與緩存相關(guān)的設(shè)置
1.可以在MyBatis 全局配置文件中的setting標(biāo)簽中配置cacheEnabled屬性,表示是否啟用二級緩存機(jī)制,不過不影響一級緩存。
2.select查詢標(biāo)簽中可以設(shè)置useCache屬性,配置是否使用二級緩存,默認(rèn)一級緩存是一直生效的。
3.sqlSession.clearCache();方法默認(rèn)只清除一級緩存中的數(shù)據(jù)。
4.可以在每個增刪改的標(biāo)簽中設(shè)置flushCache屬性,設(shè)置為true后,如果執(zhí)行了該增刪改操作,則一級緩存與二級緩存中的數(shù)據(jù)都會清空。
六、總結(jié)
這篇博客主要對MyBatis 中的二級緩存機(jī)制做了介紹,在實際開發(fā)的過程中,MyBatis 提供的二級緩存機(jī)制好像并沒有獲得開發(fā)人員的青睞。原因是二級緩存是一個namespace級別的緩存,如果在不同的namespace下操作同一SQL 語句,可能導(dǎo)致緩存中的數(shù)據(jù)不正確。在進(jìn)行多表聯(lián)查的時候,也可能會導(dǎo)致二級緩存中的數(shù)據(jù)不正確。所以在實際的開發(fā)過程中要慎用二級緩存。
總結(jié)
以上是生活随笔為你收集整理的浅谈MyBatis二级缓存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈MyBatis一级缓存
- 下一篇: MyBatis运行原理(一)SqlSes