Mybatis學習之緩存(九)

這里寫目錄標題

  • 一、MyBatis的一級緩存
    • 1.1、工作原理
    • 1.2、一級緩存失效的四種情況
    • 1.3、不同的SqlSession對應不同的一級緩存
    • 1.4、同一個SqlSession但是查詢條件不同
    • 1.5、同一個SqlSession兩次查詢期間執行了任何一次增刪改操作
    • 1.6、同一個SqlSession兩次查詢期間手動清空了(一級)緩存
  • 二、MyBatis的二級緩存
    • 2.1、二級緩存開啟的條件
    • 2.2、測試
    • 2.3、二級緩存的相關配置
      • (1)eviction屬性:緩存回收策略
      • (2)flushInterval屬性:刷新間隔,單位毫秒
      • (3)size屬性:引用數目,正整數
      • (4)readOnly屬性:只讀,true/false
  • 三、整合第三方緩存EHCache
    • 3.1、pom.xml文件中添加依賴:
    • 3.2、創建EHCache的配置文件ehcache.xml
    • 3.3、設置二級緩存類型
    • 3.4、加入logback日志

數據庫查詢是應用性能的常見瓶頸(磁盤IO比內存IO慢10^6倍以上),緩存通過將頻繁查詢的結果存儲在內存中,避免重復訪問數據庫。
MyBatis提供兩級緩存,工作流如下:

  1. 一級緩存(SqlSession級別):默認開啟,緩存當前會話的查詢結構;
  2. 二級緩存(Mapper級別):需手動開啟,緩存Mapper接口的查詢結果,可以被多個SqlSession共享。
    查詢數據時,MyBatis的緩存查詢順序:
二級緩存——>一級緩存——>數據庫

即先查詢二級緩存,若為命中則查詢一級緩存,仍為命中才查詢數據庫。

一、MyBatis的一級緩存

一級緩存是SqlSession級別的,通過同一個SqlSession查詢的數據會被緩存,下次查詢相同的數據就會從緩存中直接獲取,不會從數據庫重新訪問。整個查詢是綁定到SqlSession(會話),生命周期與SqlSession一致。

1.1、工作原理

  • 緩存范圍 :每個SqlSession擁有獨立的一級緩存,不同SqlSession的緩存互不影響;
  • 緩存時機 :SqlSession執行select查詢后,會將結果存入一級緩存;
  • 命中條件 :相同的Mapper方法+相同的參數+相同的SQL;
  • 失效場景 :SqlSession執行insert/update/delete(會清空當前SqlSession的一級緩存)、SqlSession關閉或提交。

1.2、一級緩存失效的四種情況

  1. 不同的SqlSession對應不同的一級緩存
  2. 同一個SqlSession但是查詢條件不同
  3. 同一個SqlSession兩次查詢期間執行了任何一次增刪改操作
  4. 同一個SqlSession兩次查詢期間手動清空了緩存

1.3、不同的SqlSession對應不同的一級緩存

CacheMapper.java文件:

Emp getEmpById(Integer eid);

CacheMappe.xml文件:

    <select id="getEmpById" resultType="Emp">select * from t_emp where 1=1<if test="eid != null and eid != ''">and eid = #{eid}</if></select>

測試文件:

@Testpublic void testCache() throws IOException {SqlSession sqlSession = SqlSessionUtils.getSqlSession();CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);System.out.println("第一次查詢(未命中緩存,查詢數據庫)");Emp emp1 = mapper.getEmpById(13);System.out.println(emp1);System.out.println("\n第二次查詢(相同SqlSession+相同參數,命中一級緩存,不查數據庫");Emp emp2 = mapper.getEmpById(13);System.out.println(emp2);System.out.println("\n即使用的不是同一個Mapper,也同樣從緩存中取(同一個sqlsession)");CacheMapper mapper2 = sqlSession.getMapper(CacheMapper.class);Emp empByMapper2 = mapper2.getEmpById(13);System.out.println(empByMapper2);System.out.println("\n一級緩存的范圍在sqlsession中,換一個新的sqlsession就會再次用sql讀取數據");SqlSession sqlSession2 = SqlSessionUtils.getSqlSession();CacheMapper mapper2BySqlSession2 = sqlSession2.getMapper(CacheMapper.class);System.out.println(mapper2BySqlSession2.getEmpById(13));}

測試結果:
在這里插入圖片描述

1.4、同一個SqlSession但是查詢條件不同

    @Testpublic void testCache2() throws IOException {SqlSession sqlSession = SqlSessionUtils.getSqlSession();CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);System.out.println("=====第一次獲取數據=====");Emp emp1 = mapper.getEmpById(13);System.out.println(emp1);System.out.println("\n=====查詢條件不同=====");Emp emp2 = mapper.getEmpById(12);System.out.println(emp2);}

在這里插入圖片描述

1.5、同一個SqlSession兩次查詢期間執行了任何一次增刪改操作

    @Testpublic void testCache3() throws IOException {SqlSession sqlSession = SqlSessionUtils.getSqlSession();CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);System.out.println("=====第一次獲取數據=====");Emp emp1 = mapper.getEmpById(13);System.out.println(emp1);Emp emp2 = mapper.getEmpById(13);System.out.println(emp2);System.out.println("\n=====進行增刪改操作=====");mapper.insetEmp(new Emp(null, "Joey", 44, "男", "8888@gmai.com"));System.out.println("\n=====同一個sqlsession,再獲取數據=====");Emp emp3 = mapper.getEmpById(13);System.out.println(emp3);}

在這里插入圖片描述

1.6、同一個SqlSession兩次查詢期間手動清空了(一級)緩存

    @Testpublic void testCache4() throws IOException {SqlSession sqlSession = SqlSessionUtils.getSqlSession();CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);System.out.println("=====第一次獲取數據=====");Emp emp1 = mapper.getEmpById(13);System.out.println(emp1);System.out.println("\n=====兩次查詢期間手動清空緩存=====");sqlSession.clearCache();System.out.println("\n=====再次查詢id=3的emp=====");Emp emp2 = mapper.getEmpById(13);System.out.println(emp2);}

在這里插入圖片描述

二、MyBatis的二級緩存

二級緩存是跨SqlSession的全局緩存,綁定到Mapper接口(同一個Mapper的所有方法共享),需手動開啟。
二級緩存是SqlSessionFactory級別,通過同一個SqlSessionFactory創建的SqlSession查詢的結果被緩存,此后若再次執行相同的查詢語句,結構就會從緩存中獲取。
注意:使二級緩存失效的情況:兩次查詢之間執行了任意的增刪改,會使一級和二級緩存同時失效,沒有提交sqlsession時,贖回包保存在一級緩存中,提交后,會保存在二級緩存中。

2.1、二級緩存開啟的條件

  1. 在核心配置文件中,設置全局配置屬性(在settings里面設置)
	<setting name="cacheEnabled" value="true"/>
  1. 在隱射文件中設置標簽
  2. 二級緩存必循在SqlSession關閉活提交之后有效
  3. 查詢的數據所轉換的實體類類型必須實現序列化的接口

2.2、測試

	    @Testpublic void testCacheTwo(){//這里不能用工具類了,因為每次都會創建新的sqlsessionfactory//SqlSession sqlSession = SqlSessionUtils.getSqlSession();//CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);//只要是同一個sqlsessionfactory獲得的sqlsession就可以try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);SqlSession sqlSession1 = sqlSessionFactory.openSession(true);CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);System.out.println(mapper1.getEmpById(13));//打開二級緩存未打開sqlSession1.close();System.out.println("Cache Hit Ratio:緩存命中率,指的是在緩存中有沒有這條數據");System.out.println("=====二級緩打開,從緩存中獲取數據=====");SqlSession sqlSession2 = sqlSessionFactory.openSession(true);CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);System.out.println(mapper2.getEmpById(13));} catch (IOException e) {e.printStackTrace();}}

2.3、二級緩存的相關配置

在mapper配置文件中添加的cache標簽可以設置一些屬性:

(1)eviction屬性:緩存回收策略

LRU(Least Recently Used) – 最近最少使用的:移除最長時間不被使用的對象。
FIFO(First in First out) – 先進先出:按對象進入緩存的順序來移除它們。
SOFT – 軟引用:移除基于垃圾回收器狀態和軟引用規則的對象。
WEAK –弱引用:更積極地移除基于垃圾收集器狀態和弱引用規則的對象。
默認的是 LRU。

(2)flushInterval屬性:刷新間隔,單位毫秒

默認情況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句(增刪改) 時刷新

(3)size屬性:引用數目,正整數

代表緩存最多可以存儲多少個對象,太大容易導致內存溢出

(4)readOnly屬性:只讀,true/false

  • true:只讀緩存; 會給所有調用者返回緩存對象的相同實例。因此這些對象不能被修改。這提供了很重要的性能優勢。【性能好】
  • false:讀寫緩存; 會返回緩存對象的拷貝(通過序列化)。這會慢一些,但是安全,因此默認是 false。【安全】

三、整合第三方緩存EHCache

EHCache只能替代二級緩存,所以只要了解會配置即可。

3.1、pom.xml文件中添加依賴:

	<!-- Mybatis EHCache整合包 --> 
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.1</version>
</dependency><!-- slf4j日志門面的一個具體實現 --> 
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency>

各種jar包的功能
在這里插入圖片描述

3.2、創建EHCache的配置文件ehcache.xml

<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盤保存路徑 -->
<diskStore path="這里改成你需要保存緩存的磁盤路徑"/><defaultCachemaxElementsInMemory="1000"maxElementsOnDisk="10000000"eternal="false"overflowToDisk="true"timeToIdleSeconds="120"timeToLiveSeconds="120"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache>
</ehcache>

"…/config/ehcache.xsd”報錯,則創建這個文件

3.3、設置二級緩存類型

在相對應的xxxMapper.xml中,加入:

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

3.4、加入logback日志

存在SLF4J時,作為簡易日志的log4j將失效,此時我們需要借助SLF4J的具體實現logback來打印日志。
創建logback的配置文件logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true"> <!-- 指定日志輸出的位置 --><appender name="STDOUT">class="ch.qos.logback.core.ConsoleAppender"><encoder><!-- 日志輸出的格式 --><!-- 按照順序分別是:時間、日志級別、線程名稱、打印日志的類、日志主體內容、換行 --><pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern></encoder></appender><!-- 設置全局日志級別。日志級別按順序分別是:DEBUG、INFO、WARN、ERROR --><!-- 指定任何一個日志級別都只打印當前級別和后面級別的日志。 --><root level="DEBUG"><!-- 指定打印日志的appender,這里通過“STDOUT”引用了前面配置的appender --><appender-ref ref="STDOUT" /></root><!-- 根據特殊需求指定局部日志級別 --><logger name="com.atguigu.mybatis.mapper" level="DEBUG"/>
</configuration>

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

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

相關文章

windows10裝Ubuntu22.04系統(雙系統)

參考鏈接&#xff1a;Windows和Linux雙系統的保姆級安裝教程&#xff0c;新手小白跟著也能裝_windows安裝linux雙系統-CSDN博客 1 前期準備 1.下載Ubuntu22.04.5 的iso鏡像文件&#xff1a;Download Ubuntu Desktop | Ubuntu 2.準備一個U盤&#xff08;空&#xff0c;已有文…

Pandas數據處理與分析實戰:Pandas數據清洗與處理入門

數據清洗&#xff1a;Pandas數據處理入門 學習目標 本課程將引導學員了解數據清洗的基本概念&#xff0c;掌握使用Pandas庫處理數據集中的缺失值、重復數據和異常值的方法&#xff0c;確保數據的質量&#xff0c;為后續的數據分析和機器學習任務打下堅實的基礎。 相關知識點 Pa…

Python爬蟲實戰:研究ScrapyRT框架,構建圖書商城數據采集系統

1. 引言 1.1 研究背景 在當今數字化時代,互聯網已成為全球最大的信息庫,蘊含著海量的有價值數據,涵蓋商業、教育、科研、醫療等各個領域。根據 IDC(國際數據公司)預測,到 2025 年全球數據圈將增長至 175ZB,其中網絡數據占比超過 60%。這些數據不僅是企業制定商業策略、…

springboot接口請求參數校驗

參數校驗 參數校驗可以防止無效或錯誤的數據進入系統。通過校驗前端輸入的參數&#xff0c;可以確保數據的完整性&#xff0c;避免因為缺少必要的信息而導致程序錯誤或異常。例如&#xff0c;對于密碼字段&#xff0c;可以通過校驗規則要求用戶輸入至少8個字符、包含字母和數字…

Docker部署 Neo4j 及集成 APOC 插件:安裝與配置完整指南(docker-compose)

Docker部署 Neo4j 及集成 APOC 插件&#xff1a;分步驟指南 摘要 &#xff1a;本文將分兩部分詳細介紹相關內容。第一部分講解如何使用 Docker Compose 部署 Neo4j 圖數據庫&#xff0c;提供完整配置文件及常見問題解決方案&#xff1b;第二部分在前者基礎上&#xff0c;介紹 A…

TLSv1.2協議與TCP/UDP協議傳輸數據內容差異

一、Wireshark中常見的TLSv1.2在用Wireshark抓包時&#xff0c;除了看到課堂上教過的經典的TCP/UDP協議&#xff0c;還有一個協議經常出現——TLSv1.2。并且這個協議的Info解釋是Application data&#xff0c;其實看到這個解釋&#xff0c;我大概猜出來了TLSv1.2是用來給用戶數…

51c自動駕駛~合集14

自己的原文哦~ https://blog.51cto.com/whaosoft/11707335 #Text2LiDAR 文本引導的無條件點云生成新SOTA 論文題目&#xff1a;《Text2LiDAR: Text-guided LiDAR Point Cloud Generation via Equirectangular Transformer》 論文地址&#xff1a;https://arxiv.o…

k8s基本概念

k8s 的基本概念 Kubernetes是一個可以移植、可擴展的開源平臺&#xff0c;使用 聲明式的配置 并依據配置信息自動地執行容器化應用程序的管理。在所有的容器編排工具中&#xff08;類似的還有 docker swarm / mesos等&#xff09;&#xff0c;Kubernetes的生態系統更大、增長更…

Easysearch 數據遷移之數據比對

上一篇我們通過 INFINI Gateway 進行了索引數據遷移&#xff0c;對索引遷移結果進行了初步且直觀的校驗--對比索引的文檔數是否一致。今天介紹個實實在在的數據比對方法&#xff0c;通過網關對比索引文檔的內容在兩個集群是否一致。話不多說&#xff0c;就拿上次遷移的兩個索引…

Codeforces Round 1042 (Div. 3)

ABCD 略E注意到每個操作最多執行一次&#xff0c;ifa[i]!b[i]&#xff0c;要么a[i]^a[i1]要么a[i]^b[i1]G設消除1~i的數的操作次數為f[i]&#xff0c;可以推出f[i]2*f[i-1]1&#xff0c;那么消除1~i的數的分數乘的數為g[i]&#xff0c;g[i]g[i-1]*g[i-1]*i s雖然很大&#xff0…

AJAX:讓你的網頁“靜悄悄”變聰明,體驗絲滑升級

大家好&#xff0c;今天想聊聊一個讓網頁“活”起來的小秘密——AJAX。你可能遇到過這種情況&#xff1a;點個按鈕&#xff0c;頁面就刷新&#xff0c;等得心急火燎。但用了AJAX的網站&#xff0c;比如購物車更新或搜索建議&#xff0c;數據嗖嗖就來了&#xff0c;整個頁面卻紋…

【iOS】Block基礎知識和底層探索

文章目錄前言Block的聲明和創建問題引入Block的底層結構Block的執行流程Block的創建與存儲Block的傳遞與調用Block的捕獲機制捕獲局部變量捕獲全局變量小結Block的類型__block修飾符__block變量的包裝結構體block的實例結構體block的執行邏輯Block循環引用造成的原因解決方法小…

1.Ansible 自動化介紹

1-Ansible 自動化介紹 Ansible 自動化介紹 手動執行任務和自動化執行任務 手動執行任務的麻煩事&#xff1a; 很容易漏掉某個步驟&#xff0c;或者不小心執行錯步驟&#xff0c;而且很難驗證每個步驟是不是真的按預期完成了。管理一大堆服務器時&#xff0c;很容易出現配置…

2025年云手機場景適配的行業觀察

2025年的市場中&#xff0c;云手機品牌百花齊放&#xff0c;不同品牌在性能、功能和場景適配性上的差異日益顯著。隨著云計算技術的快速發展&#xff0c;云手機已從 嘗鮮工具 演變為游戲、辦公、企業運營等場景的剛需工具。現市面上也有著更多的云手機品牌&#xff0c;結合實測…

Date/Calendar/DateFormat/LocalDate

作用說明Date用于定義時間&#xff0c;提供date對象間的比較方法Calendar(日歷類),提供對時間的運算方法DateFormat是接口&#xff0c;它的實現類SimpleDateFormat用來規范時間輸出形式LocalDate&#xff0c;在JDK1.8之后引入&#xff0c;方便了對時間的運算方法介紹Date常用方…

在Python 3.8環境中安裝Python 3.6兼容包的方法

在Python 3.8環境中安裝Python 3.6兼容包的方法 用戶的需求是&#xff1a;在Python 3.8環境中重新安裝原本為Python 3.6設計的包。這通常涉及兼容性問題&#xff0c;因為Python 3.8可能引入了一些語法或API變更&#xff0c;導致舊包無法直接運行。以下是逐步解決方案&#xff…

三種DuckDB電子表格插件的union all查詢性能對比

我選取了最穩定、兼容性最好的三種&#xff1a;官方excel對應函數read_xlsx()、官方spatial對應函數st_read()、rusty_sheet對應函數read_sheet。 1.建立兩個包含前50萬和后54萬的xlsx文件&#xff0c;用于比較。利用官方excel的copy()to進行。 D copy (from v1 order by l_ord…

Python 中使用多進程編程的“三兩”問題

文章目錄一、簡介二、選擇合適的啟動方式三、手動終止所有的進程小結一、簡介 這里簡單介紹在Python中使用多進程編程的時候容易遇到的情況和解決辦法&#xff0c;有助于排查和規避某類問題&#xff0c;但是具體問題還是需要具體分析&#xff0c;后續會補充更多的內容。 二、…

Ansible部署應用

目錄Ansible概述1&#xff1a;什么是Ansible2&#xff1a;Ansible的架構組成3&#xff1a;Ansible與SaltStack的對比安裝部署Ansible服務1&#xff1a;系統環境設置2&#xff1a;安裝Ansible&#xff08;第一臺&#xff09;2&#xff1a;配置主機清單3&#xff1a;修改Ansible配…

疏老師-python訓練營-Day44預訓練模型

浙大疏錦行 知識點回顧&#xff1a; 預訓練的概念常見的分類預訓練模型圖像預訓練模型的發展史預訓練的策略預訓練代碼實戰&#xff1a;resnet18 作業&#xff1a; 嘗試在cifar10對比如下其他的預訓練模型&#xff0c;觀察差異&#xff0c;盡可能和他人選擇的不同嘗試通過ctrl進…