Mybatis中的一級二級緩存掃盲

?思維導圖:

?

? MyBatis 提供了一級緩存和二級緩存機制,用于提高數據庫查詢的性能,減少對數據庫的訪問次數。(本質上是減少IO次數)。


一級緩存


1. 概念

? 一級緩存也稱為會話緩存,它是基于 SqlSession 的緩存。在同一個 SqlSession 中,執行相同的 SQL 查詢時,MyBatis 會優先從一級緩存中獲取結果,而不是再次訪問數據庫。

2. 工作原理

2.1緩存結構:

? 在?SqlSession?內部,一級緩存是一個?PerpetualCache?對象,它本質上是一個?HashMap,鍵是根據查詢的 SQL 語句、參數、環境等信息生成的唯一標識,值是查詢結果。

? 查詢流程:當調用?SqlSession?的查詢方法時,MyBatis 會先將查詢的 SQL 語句、參數等信息組合成一個唯一的緩存鍵。然后在?PerpetualCache?這個?HashMap?中查找該鍵對應的值。如果找到了,就直接返回該值;如果沒找到,就會執行 SQL 查詢,將查詢結果存入?PerpetualCache?中,下次再執行相同查詢時就可以直接從緩存中獲取結果。

2.2 緩存命中的條件

相同的?SqlSession:必須是在同一個?SqlSession?實例中執行相同的查詢,一級緩存才會生效。
相同的 SQL 語句:查詢的 SQL 語句必須完全相同,包括 SQL 中的參數占位符和參數值。
相同的環境:查詢的環境(如數據庫連接、事務等)也必須相同。

代碼示例:

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 java.io.InputStream;public class FirstLevelCacheDetailExample {public static void main(String[] args) throws Exception {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 創建第一個 SqlSessiontry (SqlSession sqlSession1 = sqlSessionFactory.openSession()) {// 第一次查詢User user1 = sqlSession1.selectOne("com.example.UserMapper.selectUserById", 1);System.out.println("第一次查詢結果: " + user1);// 第二次查詢,使用相同的 SqlSessionUser user2 = sqlSession1.selectOne("com.example.UserMapper.selectUserById", 1);System.out.println("第二次查詢結果: " + user2);// 兩次查詢結果相同,說明使用了一級緩存System.out.println("兩次查詢結果是否相同: " + (user1 == user2));// 執行更新操作sqlSession1.update("com.example.UserMapper.updateUser", new User(1, "New Name"));// 第三次查詢User user3 = sqlSession1.selectOne("com.example.UserMapper.selectUserById", 1);System.out.println("第三次查詢結果: " + user3);// 由于執行了更新操作,一級緩存已清空,user3 是重新查詢數據庫得到的結果System.out.println("第一次查詢結果和第三次查詢結果是否相同: " + (user1 == user3));}}
}

? 在上述代碼中,前兩次查詢使用相同的 SqlSession 和相同的查詢條件,所以第二次查詢會從一級緩存中獲取結果。而執行更新操作后,一級緩存被清空,第三次查詢會重新訪問數據庫。

3. 緩存失效情況

  • 不同的?SqlSession:每個?SqlSession?都有自己獨立的一級緩存,不同的?SqlSession?之間的緩存是不共享的。
  • 執行?insert、update、delete?操作:當在同一個?SqlSession?中執行這些操作時,會清空該?SqlSession?的一級緩存,以保證數據的一致

4. 優缺點

優點:

  • 提高性能:在同一個 SqlSession 中多次執行相同查詢時,避免了重復的數據庫訪問,減少了數據庫的負載,提高了查詢性能。
  • 簡單易用:一級緩存是 MyBatis 內置的,無需額外配置,默認開啟,使用方便。

缺點:

  • 作用范圍小:只在同一個 SqlSession 中有效,不同的 SqlSession 之間無法共享緩存,限制了緩存的使用范圍。
  • 數據一致性問題:如果在同一個 SqlSession 中執行了 insert、update、delete 操作,會清空該 SqlSession 的一級緩存,但如果在不同的 SqlSession 中對同一數據進行了修改,一級緩存可能會返回舊數據,導致數據不一致。

二級緩存

1. 工作原理

緩存結構:

二級緩存也是基于 PerpetualCache 實現的,但它是基于 SqlSessionFactory 的。每個 Mapper 可以有自己獨立的二級緩存,也可以多個 Mapper 共享同一個二級緩存。

查詢流程:當一個 SqlSession 執行查詢操作時,MyBatis 會先檢查該 Mapper 對應的二級緩存中是否存在該查詢結果。如果存在,則直接從二級緩存中獲取結果;如果不存在,則執行 SQL 查詢,并將查詢結果存入二級緩存中。在多個 SqlSession 之間,只要它們是由同一個 SqlSessionFactory 創建的,就可以共享二級緩存。

2. 配置詳解

全局配置:在 mybatis-config.xml 中開啟二級緩存的全局開關。

<settings><setting name="cacheEnabled" value="true"/>
</settings>

?Mapper 配置:在 Mapper 映射文件中配置緩存。

<mapper namespace="com.example.UserMapper"><!-- 開啟二級緩存,并配置相關屬性 --><cacheeviction="LRU" <!-- 緩存淘汰策略,這里使用最近最少使用策略 -->flushInterval="60000" <!-- 緩存刷新間隔,單位為毫秒 -->size="512" <!-- 緩存的最大對象數 -->readOnly="true" /> <!-- 是否只讀 --><select id="selectUserById" resultType="com.example.User">SELECT * FROM users WHERE id = #{id}</select>
</mapper>

  • eviction:緩存淘汰策略,常見的有 LRU(最近最少使用)、FIFO(先進先出)等。
  • flushInterval:緩存刷新間隔,指定多長時間清空一次緩存。
  • size:緩存的最大對象數,當緩存中的對象數量超過該值時,會根據淘汰策略淘汰部分對象。
  • readOnly:是否只讀。如果設置為 true,則緩存中的對象是只讀的,MyBatis 會直接返回緩存中的對象,不會進行序列化和反序列化操作,性能較高;如果設置為 false,則每次返回緩存中的對象時都會進行序列化和反序列化操作,保證返回的對象是一個新的實例,但性能相對較低。

3. 示例代碼及分析

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 java.io.InputStream;public class SecondLevelCacheDetailExample {public static void main(String[] args) throws Exception {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 第一個 SqlSessiontry (SqlSession sqlSession1 = sqlSessionFactory.openSession()) {User user1 = sqlSession1.selectOne("com.example.UserMapper.selectUserById", 1);System.out.println("第一個 SqlSession 查詢結果: " + user1);}// 第二個 SqlSessiontry (SqlSession sqlSession2 = sqlSessionFactory.openSession()) {User user2 = sqlSession2.selectOne("com.example.UserMapper.selectUserById", 1);System.out.println("第二個 SqlSession 查詢結果: " + user2);// 兩次查詢結果相同,說明使用了二級緩存System.out.println("兩次查詢結果是否相同: " + (user1 == user2));}// 執行更新操作try (SqlSession sqlSession3 = sqlSessionFactory.openSession()) {sqlSession3.update("com.example.UserMapper.updateUser", new User(1, "New Name"));sqlSession3.commit(); // 提交事務,清空二級緩存}// 第三個 SqlSessiontry (SqlSession sqlSession4 = sqlSessionFactory.openSession()) {User user3 = sqlSession4.selectOne("com.example.UserMapper.selectUserById", 1);System.out.println("第三個 SqlSession 查詢結果: " + user3);// 由于執行了更新操作,二級緩存已清空,user3 是重新查詢數據庫得到的結果System.out.println("第一個查詢結果和第三個查詢結果是否相同: " + (user1 == user3));}}
}

?

? 在上述代碼中,第一個 SqlSession 執行查詢后,結果會存入二級緩存。第二個 SqlSession 執行相同查詢時,會從二級緩存中獲取結果。執行更新操作并提交事務后,二級緩存會被清空,第三個 SqlSession 執行查詢時會重新訪問數據庫。

3. 緩存失效情況

  • 執行 insert、update、delete 操作:當執行這些操作時,會清空該 Mapper 對應的二級緩存,以保證數據的一致性。
  • 緩存刷新策略:可以通過配置緩存的刷新策略,如 flushInterval 來定期清空緩存。

4. 優缺點

優點

  • 作用范圍大:多個 SqlSession 可以共享二級緩存,減少了數據庫的訪問次數,提高了系統的整體性能。
  • 可配置性強:可以通過配置不同的緩存淘汰策略、刷新間隔等參數,滿足不同的業務需求。

缺點

  • 配置復雜:需要在全局配置和 Mapper 映射文件中進行配置,相對一級緩存來說配置較為復雜。
  • 數據一致性問題:如果在不同的 Mapper 中對同一數據進行了修改,可能會導致二級緩存中的數據不一致,需要手動清空緩存或使用更復雜的緩存刷新策略。

5.一級緩存和二級緩存的比較

作用范圍:一級緩存是基于 SqlSession 的,作用范圍較小;二級緩存是基于 SqlSessionFactory 的,作用范圍較大。

緩存共享:一級緩存不共享,每個 SqlSession 有自己獨立的緩存;二級緩存可以在多個 SqlSession 之間共享。

開啟方式:一級緩存默認開啟;二級緩存需要手動配置開啟。
通過合理使用一級緩存和二級緩存,可以有效提高 MyBatis 應用的性能。但在使用緩存時,需要注意數據的一致性問題,避免出現臟數據。

總結

? MyBatis 的一級緩存和二級緩存各有優缺點,在實際應用中需要根據具體的業務場景合理使用。一級緩存適用于在同一個 SqlSession 中多次執行相同查詢的場景,而二級緩存適用于多個 SqlSession 之間共享緩存的場景。同時,需要注意緩存的使用可能會導致數據一致性問題,需要在業務邏輯中進行相應的處理。

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/web/78157.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/web/78157.shtml
    英文地址,請注明出處:http://en.pswp.cn/web/78157.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    uniapp 實現低功耗藍牙連接并讀寫數據實戰指南

    在物聯網應用場景中&#xff0c;低功耗藍牙&#xff08;BLE&#xff09;憑借其低能耗、連接便捷的特點&#xff0c;成為設備間數據交互的重要方式。Uniapp 作為一款跨平臺開發框架&#xff0c;提供了豐富的 API 支持&#xff0c;使得在多個端實現低功耗藍牙功能變得輕松高效。本…

    OpenSSL應用實踐:嵌入式數據安全實戰指南

    文章目錄 OpenSSL應用實踐:嵌入式數據安全實戰指南一、嵌入式安全現狀與OpenSSL適配方案1.1 嵌入式安全挑戰1.2 OpenSSL精簡方案二、開發環境搭建2.1 交叉編譯工具鏈2.2 OpenSSL交叉編譯三、核心功能實現3.1 AES-GCM加密實踐四、實戰項目:安全OTA升級4.1 系統架構4.2 關鍵代碼…

    harmonyOS 手機,雙折疊,平板,PC端屏幕適配

    由于HarmonyOS設備的屏幕尺寸和分辨率各不相同&#xff0c;開發者需要采取適當的措施來適配不同的屏幕。 1.EntryAbility.ets文件里&#xff1a;onWindowStageCreate方法里判斷設備類型&#xff0c; 如果是pad&#xff0c;需全屏展示&#xff08;按客戶需求來&#xff0c;本次…

    跟韓學AiOps系列之2025學MySQL系列_如何在MySQL中開啟和提交事務?!

    跟韓學AiOps系列之2025學MySQL系列_如何在MySQL中開啟和提交事務&#xff1f;! 文章目錄 一、事務的基本操作1. 開啟事務2. 執行事務內操作3. 提交事務4. 回滾事務 二、驗證示例&#xff08;適用于 MySQL 5.7&#xff09;步驟 1&#xff1a;準備測試表和數據步驟 2&#xff1a…

    Java生成微信小程序碼及小程序短鏈接

    使用wx-java-miniapp-spring-boot-starter 生成微信小程序碼及小程序短鏈接 在pom.xml文件中引入依賴 <dependency><groupId>com.github.binarywang</groupId><artifactId>wx-java-miniapp-spring-boot-starter</artifactId><version>4.7…

    如何讓通義千問大模型支持結構化輸出?

    之前的文章提到通義千問API無法通過with_structured_output/json schema的方式支持結構化輸出&#xff0c;如果就是想使用通義千問大模型做結構化輸出&#xff0c;應該怎么辦呢&#xff1f;有兩種辦法 使用Ollama來運行通義千問大模型 從Ollama博客文章 Structured output 中…

    一條 SQL 查詢語句是如何執行的(MySQL)

    第一講&#xff1a;一條 SQL 查詢語句是如何執行的 總覽圖示 MySQL 查詢的執行流程可以大致分為以下步驟&#xff08;如圖所示&#xff09;&#xff1a; 連接器&#xff08;Connection&#xff09;查詢緩存&#xff08;Query Cache&#xff0c;MySQL 8.0 已廢棄&#xff09;…

    汽車OTA在線升級法規分析

    摘要 本文介紹了R156法規即《關于批準車輛的軟件升級和軟件升級管理體系統一規定的法規》、該法規專注于汽車軟件升級功能&#xff0c;并為此提出了一系列具體要求&#xff0c;旨在確保軟件升級流程的安全性、可控性和合規性&#xff0c;從而順應汽車行業智能化、聯網化的發展趨…

    Notepad編輯器實現換行符替換

    在不同的Note編輯器中&#xff0c;批量把換行替換為空的方法有所不同&#xff0c;以下是常見編輯器的操作方法&#xff1a; Notepad 打開文件后&#xff0c;按CtrlH打開“查找和替換”對話框&#xff0c;在“查找”字段中輸入\r\n&#xff0c;在“替換為”字段中輸入一個空格…

    Rust多線程性能優化:打破Arc+鎖的瓶頸,效率提升10倍

    一、引言 在 Rust 開發中&#xff0c;多線程編程是提升程序性能的重要手段。Arc&#xff08;原子引用計數&#xff09;和鎖的組合是實現多線程數據共享的常見方式。然而&#xff0c;很多程序員在使用 Arc 和鎖時會遇到性能瓶頸&#xff0c;導致程序運行效率低下。本文將深入剖…

    【安裝指南】Centos7 在 Docker 上安裝 RabbitMQ4.0.x

    目錄 前置知識:RabbitMQ 的介紹 一、單機安裝 RabbitMQ 4.0.7版本 1.1 在線拉取鏡像 二、延遲插件的安裝 2.1 安裝延遲插件 步驟一:下載延遲插件 步驟二:將延遲插件放到插件目錄 步驟三:啟動延遲插件 步驟四:重啟 RabbitMQ 服務 步驟五:驗收成果 步驟六:手動…

    【quantity】5 derive_more庫 2.0 版介紹

    derive_more 是一個 Rust 過程宏庫&#xff0c;旨在通過派生宏自動生成常見 trait 的實現&#xff0c;減少樣板代碼。2.0 版本帶來了多項改進和新特性。 主要特性 1. 支持的 Trait 派生 derive_more 2.0 支持派生以下 trait&#xff1a; 基本操作 trait: Display - 格式化顯…

    網站備份,網站數據備份的步驟

    網站備份&#xff08;尤其是網站數據備份&#xff09;是保障業務連續性、防止數據丟失和應對安全威脅的關鍵措施。以下是系統化的備份步驟和實施建議&#xff0c;涵蓋技術操作、策略規劃及常見問題處理&#xff1a; 一、備份前的準備工作 明確備份范圍 核心數據&#xff1a;…

    OpenCV 圖形API(72)圖像與通道拼接函數-----根據指定的方式翻轉圖像(GMat)函數 flip()

    操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 翻轉一個2D矩陣&#xff0c;圍繞垂直軸、水平軸或同時圍繞兩個軸。 該函數以三種不同的方式之一翻轉矩陣&#xff08;行和列的索引是從0開始的&a…

    醫生視角下轉錄組學的生物信息學分析

    醫生視角下轉錄組學的生物信息學分析 轉錄組學的生物信息學分析是醫生解決臨床與科研問題的有力工具。這里羅列醫學轉錄組學相關的幾個概念&#xff0c;從使用者&#xff08;醫生&#xff09;的角度看待理解相關技術&#xff0c;為后續使用該技術說明臨床和科研問題奠定基礎。…

    量子機器學習中的GPU加速實踐:基于CUDA Quantum的混合編程模型探索

    引言&#xff1a;量子機器學習的新范式 在量子計算與經典機器學習交叉融合的前沿領域&#xff0c;量子機器學習&#xff08;Quantum Machine Learning, QML&#xff09;正經歷著革命性突破。然而&#xff0c;隨著量子比特規模的增長和算法復雜度的提升&#xff0c;傳統計算架構…

    Matplotlib核心課程-2

    4.1 數據加載、儲存 4.1.1 從數據文件讀取數據 導入支持庫&#xff1a; import numpy as np from pandas import Series,DataFrame import pandas as pd 從csv文件讀取數據&#xff0c;一般方法&#xff1a; pd.read_csv(../data/ex1.csv,encodinggbk) 從csv文件讀取數據&#…

    new和malloc的區別

    1 語義層級不同&#xff1a;語言機制 vs. 庫函數 new / new[] (C 關鍵字)malloc / calloc / realloc (C 運行時函數)本質語言級運算符&#xff1b;可被重載庫函數&#xff1b;無法重載作用分配內存 并調用構造函數僅分配原始字節塊&#xff0c;不做初始化&#xff0c;也不調用…

    C++11新特性_自動類型推導_auto

    在 C11 標準中&#xff0c;auto關鍵字被賦予了全新且強大的功能&#xff0c;它用于自動類型推導&#xff0c;即編譯器能夠根據變量的初始化表達式自動確定其類型。 基本語法 使用auto聲明變量時&#xff0c;只需給出auto關鍵字&#xff0c;后面緊跟變量名&#xff0c;并對其進…

    [預備知識]6. 優化理論(二)

    優化理論 本章節介紹深度學習中的高級優化技術&#xff0c;包括學習率衰減、梯度裁剪和批量歸一化。這些技術能夠顯著提升模型的訓練效果和穩定性。 學習率衰減&#xff08;Learning Rate Decay&#xff09; 數學原理與可視化 學習率衰減策略的數學表達&#xff1a; 步進式…