一、什麼是快取
快取是記憶體當中一塊儲存資料的區域,目的是提高查詢效率。 MyBatis會將查詢結果儲存在快取當中,當下次執行相同的SQL時不存取資料庫,而是直接從快取中取得結果,從而減少伺服器的壓力。
什麼是快取?
存在於記憶體中的一塊資料。
快取有什麼作用?
減少程式和資料庫的交互,提高查詢效率,降低伺服器和資料庫的壓力。
什麼樣的資料使用快取?
經常查詢但不常改變的,改變後對結果影響不大的資料。
MyBatis快取分為哪幾類?
一級快取和二級快取
如何判斷兩次Sql是相同的?
查詢的Sql語句相同傳遞的參數值相同對結果集的要求相同預先編譯的模板Id相同
二、Mabtis一級快取
MyBatis一級快取也叫本地快取。 SqlSession物件中包含一個Executor對象,Executor物件中包含一個PerpetualCache對象,在該物件存放一級快取資料。
由於一級快取是在SqlSession物件中,所以只有使用同一個SqlSession物件操作資料庫時才能共享一級快取。
MyBatis的一級快取是預設為開啟的,不需要任何的配置。
如下圖所示:
#(1)測試一級快取
其實測試方法很簡單,就是透過使用相同且不同的SqlSession物件進行SQL查詢,傳回的物件的雜湊值是否一樣就可以知道了,如果傳回的雜湊值一樣說明沒有進行SQL查詢,而是直接從快取拿到物件來返回
下面是使用相同的Session物件來執行查詢,如果觀察user1和user2的雜湊值一樣則說明確實開啟了一級緩存,並沒有進行查詢,而是直接從快取拿資料。
import com.mybatisstudy.mapper.UserMapper; import com.mybatisstudy.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.InputStream; public class TestUserMapper3 { // 测试使用同一个SqlSession查询 @Test public void testCache1() throws Exception{ InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); // 使用同一个SqlSession查询 UserMapper mapper1 = session.getMapper(UserMapper.class); UserMapper mapper2 = session.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1.hashCode()); System.out.println("------------------------------------------"); User user2 = mapper2.findById(1); System.out.println(user2.hashCode()); session.close(); } }
執行結果
OK,確實回傳的哈希值都是一樣的,且我們可以透過控制台輸出顯示它並沒有進行查詢而是直接從快取中拿到物件並返回,所以這就是一級緩存,提高了查詢效率。
在下方使用不同的SqlSession來進行測試一下,而傳回的雜湊值是否一致
// 测试使用不同SqlSession查询 @Test public void testCache2() throws Exception{ InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session1 = factory.openSession(); SqlSession session2 = factory.openSession(); // 测试使用不同SqlSession查询 UserMapper mapper1 = session1.getMapper(UserMapper.class); UserMapper mapper2 = session2.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1.hashCode()); System.out.println("---------------------------------"); User user2 = mapper2.findById(1); System.out.println(user2.hashCode()); session1.close(); session2.close(); }
#執行結果
// 清空Mybatis一级缓存 @Test public void testCache3() throws Exception{ InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); UserMapper mapper1 = session.getMapper(UserMapper.class); UserMapper mapper2 = session.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1.hashCode()); // 清空Mybatis一级缓存 session.clearCache(); System.out.println("-------------------------------"); User user2 = mapper2.findById(1); System.out.println(user2.hashCode()); session.close(); }
import java.io.Serializable; public class User implements Serializable { private int id; private String username; private String sex; private String address; }
## OK,可以看到,返回的雜湊值不一樣,並且從控制台輸出顯示也可以看到這裡的確也進行了一次查詢,因此可以證實,
共用一級快取確實是基於SqlSession物件的##(2)清空一級快取
- 但是吧,如果快取過多的話,也是會影響我們的查詢效率的,所以這時候就需要清空快取了,就像我們時不時要清理一下手機快取否則就會很卡,是同樣的道理,那怎麼清空一級快取呢?
可以清空MyBatis一級快取:
SqlSession 呼叫close() :操作後SqlSession物件不可用,該物件的快取資料也不可用。
###SqlSession 呼叫增刪改方法:操作會清空一級快取數據,因為增刪改後資料庫發生改變,快取資料將不準確########### #<!-- 二级缓存打开 --> <settings> <setting></setting> </settings>######執行效果###################### OK,回傳的雜湊值確實不一樣, 但是我們有沒有觀察到這和上面使用不同的SqlSession物件來執行查詢的時候,控制台輸入顯示有點不一樣,那就是這裡不用再建立JDBC連接,也有效了提高查詢效率,所以我們偶爾還是要清空一下緩存才行###
三、Mybatis二级缓存
MyBatis二级缓存也叫全局缓存。数据存放在SqlSessionFactory中,只要是同一个工厂对象创建的SqlSession,在进行查询时都能共享数据。一般在项目中只有一个SqlSessionFactory对象,所以二级缓存的数据是全项目共享的。
MyBatis一级缓存存放的是对象,二级缓存存放的是对象的数据。所以要求二级缓存存放的POJO必须是可序列化的,也就是要实现Serializable接口。
MyBatis二级缓存默认不开启,手动开启后数据先存放在一级缓存中,只有一级缓存数据清空后,数据才会存到二级缓存中。
SqlSession 调用 clearCache() 无法将数据存到二级缓存中。
(1)开启二级缓存
1. POJO类实现Serializable接口
import java.io.Serializable; public class User implements Serializable { private int id; private String username; private String sex; private String address; }
2. 在Mybatis配置文件添加如下设置
<!-- 二级缓存打开 --> <settings> <setting></setting> </settings>
这里有个额外知识,就是Mybatis配置文件的标签还得按照顺序来放的,否则就会以下编译错误;
The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,
objectWrapperFactory?,reflectorFactory?,plugins?,environments?,
databaseIdProvider?,mappers?)".
同时也说明了放置顺序就得按照match里面的顺序来放
3. 添加
如果查询到的集合中对象过多,二级缓存只能缓存1024个对象引用。可以通过
标签的size属性修改该数量。 比如:
(2)测试二级缓存
那怎么测试呢,从上面我们可以知道二级缓存存放的是对象的数据,并且是基于SqlSessionFactory的,因此我们可以用SqlSessionFactory获取两个SqlSession对象,然后让他们分别获取各自的mapper,然后进行查询,返回到同一个实例化的USer对象中,如果返回的数据是一致的,但是对象的哈希值是不一样的话,则说明二级缓存里存放的确实对象的数据而不是对象。
// 测试二级缓存 @Test public void testCache4() throws Exception { InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); UserMapper mapper1 = session.getMapper(UserMapper.class); UserMapper mapper2 = session.getMapper(UserMapper.class); User user1 = mapper1.findById(1); System.out.println(user1); System.out.println(user1.hashCode()); // 让一级缓存失效 session.commit(); System.out.println("----------------------------"); user1 = mapper2.findById(1); System.out.println(user1); System.out.println(user1.hashCode()); }
运行结果
OK,从运行结果上我们可以知道结果集返回到同一个对象中,而他们的哈希值反而不一样,说明执行第二次查询的时候新建了一个对象并且该对象指向那个对象并且将SqlSessionFactory中的数据赋值到新建的那个对象。其实从控制台打印的日志我们也可以得出,并没有执行查询方法,因为没有打印SQL语句,而且缓存也是从0.0改成了0.5,因此我们可以断定二级缓存存放的是数据而不是对象。
以上是Java Mybatis一級快取和二級快取是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3 Linux新版
SublimeText3 Linux最新版

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能