最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis中的緩存機(jī)制解析

 更新時(shí)間:2025年11月12日 10:08:36   作者:程序員小假  
這篇文章給大家介紹mybatis中的緩存機(jī)制,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

核心概覽

  • 一級(jí)緩存:默認(rèn)開(kāi)啟,作用范圍在 同一個(gè) SqlSession 內(nèi)。
  • 二級(jí)緩存:需要手動(dòng)配置開(kāi)啟,作用范圍在 同一個(gè) Mapper 命名空間(即同一個(gè) Mapper 接口)內(nèi),可以被多個(gè) SqlSession 共享。

一級(jí)緩存

1. 作用域

  • SqlSession 級(jí)別:當(dāng)同一個(gè) SqlSession 執(zhí)行相同的 SQL 查詢時(shí),MyBatis 會(huì)優(yōu)先從緩存中獲取數(shù)據(jù),而不是直接查詢數(shù)據(jù)庫(kù)。
  • 它是 默認(rèn)開(kāi)啟 的,無(wú)法關(guān)閉,但可以配置其作用范圍(SESSIONSTATEMENT)。

2. 工作機(jī)制

  1. 第一次執(zhí)行查詢后,查詢結(jié)果會(huì)被存儲(chǔ)到 SqlSession 關(guān)聯(lián)的一級(jí)緩存中。
  2. 在同一個(gè) SqlSession 中,再次執(zhí)行 完全相同的 SQL 查詢(包括語(yǔ)句和參數(shù))時(shí),會(huì)直接返回緩存中的對(duì)象,而不會(huì)去數(shù)據(jù)庫(kù)查詢。
  3. 如果 SqlSession 執(zhí)行了 增(INSERT)、刪(DELETE)、改(UPDATE) 操作,或者調(diào)用了 commit()、close()、rollback() 方法,該 SqlSession 的一級(jí)緩存會(huì)被清空。這是為了防止讀取到臟數(shù)據(jù)。

3. 示例說(shuō)明

// 假設(shè)獲取的 SqlSession 和 UserMapper
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    // 第一次查詢,會(huì)發(fā)送 SQL 到數(shù)據(jù)庫(kù)
    User user1 = mapper.selectUserById(1L);
    System.out.println(user1);
    // 第二次查詢,SQL 和參數(shù)完全相同,直接從一級(jí)緩存返回,不查詢數(shù)據(jù)庫(kù)
    User user2 = mapper.selectUserById(1L);
    System.out.println(user2);
    // 判斷是否為同一個(gè)對(duì)象(是,因?yàn)閺木彺嬷蟹祷氐氖峭粋€(gè)對(duì)象的引用)
    System.out.println(user1 == user2); // 輸出:true
    // 執(zhí)行一個(gè)更新操作
    mapper.updateUser(user1);
    // 此時(shí),一級(jí)緩存被清空
    // 第三次查詢,因?yàn)榫彺姹磺蹇眨瑫?huì)再次發(fā)送 SQL 到數(shù)據(jù)庫(kù)
    User user3 = mapper.selectUserById(1L);
    System.out.println(user3 == user1); // 輸出:false (雖然是同一條數(shù)據(jù),但已是新對(duì)象)
}

4. 注意事項(xiàng)

  • 對(duì)象相同:一級(jí)緩存返回的是 同一個(gè)對(duì)象的引用,因此在同一個(gè) SqlSession 內(nèi),你操作的都是同一個(gè) Java 對(duì)象。
  • 分布式環(huán)境:一級(jí)緩存無(wú)法在多個(gè)應(yīng)用服務(wù)器之間共享,因?yàn)樗壎ㄔ趩蝹€(gè)請(qǐng)求的 SqlSession 上。

二級(jí)緩存

1. 作用域

  • Mapper 級(jí)別 / Namespace 級(jí)別:多個(gè) SqlSession 在訪問(wèn)同一個(gè) Mapper 的查詢時(shí),可以共享其緩存。
  • 它是 默認(rèn)關(guān)閉 的,需要在全局配置中開(kāi)啟,并在具體的 Mapper XML 中顯式配置。

2. 開(kāi)啟與配置

a. 全局配置文件 (mybatis-config.xml):
必須顯式設(shè)置開(kāi)啟二級(jí)緩存(雖然默認(rèn)是 true,但顯式聲明是個(gè)好習(xí)慣)。

<configuration>
<settings>
<!-- 開(kāi)啟全局二級(jí)緩存,默認(rèn)就是 true,但建議寫(xiě)明 -->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>

b. Mapper XML 文件
在需要開(kāi)啟二級(jí)緩存的 Mapper.xml 中添加 <cache/> 標(biāo)簽。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- 開(kāi)啟本 Mapper 的二級(jí)緩存 -->
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
<!-- 其他 SQL 定義 -->
<select id="selectUserById" parameterType="long" resultType="User" useCache="true">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
  • <cache/> 標(biāo)簽屬性:
  • eviction:緩存回收策略。
  • LRU(默認(rèn)):最近最少使用。
  • FIFO:先進(jìn)先出。
  • SOFT:軟引用,基于垃圾回收器狀態(tài)和軟引用規(guī)則移除。
  • WEAK:弱引用,更積極地移除。
  • flushInterval:緩存刷新間隔(毫秒),默認(rèn)不清空。
  • size:緩存存放多少元素。
  • readOnly:是否為只讀。
  • true:返回相同的緩存對(duì)象實(shí)例,性能好,但不允許修改。
  • false(默認(rèn)):通過(guò)序列化返回緩存對(duì)象的拷貝,安全,性能稍差。

3. 工作機(jī)制

  1. 當(dāng)一個(gè) SqlSession 執(zhí)行查詢后,在關(guān)閉或提交時(shí),其查詢結(jié)果會(huì)被存入二級(jí)緩存。
  2. 另一個(gè) SqlSession 執(zhí)行相同的查詢時(shí),會(huì)先從二級(jí)緩存中查找數(shù)據(jù)。如果找到,則直接返回,否則再去數(shù)據(jù)庫(kù)查詢。
  3. 任何一個(gè) SqlSession 執(zhí)行了 增、刪、改 操作并 commit() 后,會(huì)清空 整個(gè)對(duì)應(yīng) Mapper 的二級(jí)緩存,以保證數(shù)據(jù)一致性。

4. 示例說(shuō)明

// 第一個(gè) SqlSession
try (SqlSession sqlSession1 = sqlSessionFactory.openSession()) {
    UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
    User user1 = mapper1.selectUserById(1L); // 查詢數(shù)據(jù)庫(kù)
    sqlSession1.close(); // 關(guān)閉時(shí),數(shù)據(jù)存入二級(jí)緩存
}
// 第二個(gè) SqlSession(與第一個(gè)不同)
try (SqlSession sqlSession2 = sqlSessionFactory.openSession()) {
    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
    // 查詢相同的 SQL,直接從二級(jí)緩存獲取,不查詢數(shù)據(jù)庫(kù)
    User user2 = mapper2.selectUserById(1L);
}
// 第三個(gè) SqlSession,執(zhí)行了更新
try (SqlSession sqlSession3 = sqlSessionFactory.openSession()) {
    UserMapper mapper3 = sqlSession3.getMapper(UserMapper.class);
    User user = mapper3.selectUserById(1L);
    user.setName("New Name");
    mapper3.updateUser(user); // 執(zhí)行更新
    sqlSession3.commit(); // 提交時(shí),清空 UserMapper 的二級(jí)緩存
}
// 第四個(gè) SqlSession
try (SqlSession sqlSession4 = sqlSessionFactory.openSession()) {
    UserMapper mapper4 = sqlSession4.getMapper(UserMapper.class);
    // 因?yàn)榫彺嬉驯磺蹇?,所以?huì)再次查詢數(shù)據(jù)庫(kù)
    User user4 = mapper4.selectUserById(1L);
}

5. 注意事項(xiàng)

  • 實(shí)體類序列化:如果二級(jí)緩存的 readOnly="false",那么對(duì)應(yīng)的實(shí)體類必須實(shí)現(xiàn) Serializable 接口。
  • 事務(wù)提交:只有在 SqlSession 執(zhí)行 commit()close() 時(shí),數(shù)據(jù)才會(huì)從一級(jí)緩存轉(zhuǎn)存到二級(jí)緩存。
  • 緩存粒度:二級(jí)緩存是 Mapper 級(jí)別的,有時(shí)會(huì)顯得比較粗粒度。可以通過(guò) <cache-ref> 讓多個(gè) Mapper 共享一個(gè)緩存,但不推薦,容易引起數(shù)據(jù)混亂。

緩存順序與總結(jié)

當(dāng)發(fā)起一個(gè)查詢請(qǐng)求時(shí),MyBatis 的緩存查詢順序是:

  1. 先查二級(jí)緩存:查看當(dāng)前 Mapper 的二級(jí)緩存中是否有數(shù)據(jù)。
  2. 再查一級(jí)緩存:如果二級(jí)緩存沒(méi)有,再查看當(dāng)前 SqlSession 的一級(jí)緩存中是否有數(shù)據(jù)。
  3. 最后查數(shù)據(jù)庫(kù):如果兩級(jí)緩存都沒(méi)有,才發(fā)送 SQL 語(yǔ)句到數(shù)據(jù)庫(kù)執(zhí)行查詢。

查詢到的數(shù)據(jù)會(huì) 先存入一級(jí)緩存,在 SqlSession 關(guān)閉或提交時(shí),再轉(zhuǎn)存到二級(jí)緩存。

特性

一級(jí)緩存

二級(jí)緩存

作用域

SqlSession

Mapper (Namespace)

默認(rèn)狀態(tài)

開(kāi)啟

關(guān)閉

是否共享

否,Session 獨(dú)享

是,跨 Session 共享

清空時(shí)機(jī)

UPDATE/INSERT/DELETE, commit(), close()

同 Mapper 的 UPDATE/INSERT/DELETE + commit()

使用建議

  • 查詢多,修改少的數(shù)據(jù)適合使用二級(jí)緩存,如字典表、配置項(xiàng)。
  • 數(shù)據(jù)實(shí)時(shí)性要求高的場(chǎng)景(如交易、訂單)應(yīng)謹(jǐn)慎使用二級(jí)緩存,或者設(shè)置較短的刷新間隔。
  • 在分布式環(huán)境中,默認(rèn)的二級(jí)緩存(基于內(nèi)存)是無(wú)法共享的,需要集成 Redis、Ehcache 等第三方緩存中間件來(lái)替代。
  • 理解緩存機(jī)制有助于解決一些“詭異”的問(wèn)題,比如在同一個(gè)事務(wù)中,先后查詢和更新,但由于一級(jí)緩存的存在,后續(xù)查詢可能看不到其他線程的更新。

到此這篇關(guān)于Mybatis 的緩存機(jī)制的文章就介紹到這了,更多相關(guān)mybatis 緩存機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中的connection reset 異常處理分析

    java中的connection reset 異常處理分析

    本文主要介紹了java中的connection reset 異常處理分析的相關(guān)資料,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧
    2017-04-04
  • Springboot使用Maven占位符@替換不生效問(wèn)題及解決

    Springboot使用Maven占位符@替換不生效問(wèn)題及解決

    這篇文章主要介紹了Springboot使用Maven占位符@替換不生效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Spring計(jì)時(shí)器StopWatch的具體使用

    Spring計(jì)時(shí)器StopWatch的具體使用

    本文主要介紹了Spring計(jì)時(shí)器StopWatch的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • SpringBoot項(xiàng)目啟動(dòng)執(zhí)行任務(wù)的多種方法小結(jié)

    SpringBoot項(xiàng)目啟動(dòng)執(zhí)行任務(wù)的多種方法小結(jié)

    這篇文章主要介紹了SpringBoot項(xiàng)目啟動(dòng)執(zhí)行任務(wù)的多種方法小結(jié),本文給大家分享的這幾種方法經(jīng)常會(huì)被用到,當(dāng)我們的項(xiàng)目啟動(dòng)后需要調(diào)用對(duì)應(yīng)的方法,用來(lái)項(xiàng)目的初始化等,本文通過(guò)示例代碼講解的非常詳細(xì),需要的朋友參考下吧
    2023-07-07
  • Java中的ArrayList和線性表用法及說(shuō)明

    Java中的ArrayList和線性表用法及說(shuō)明

    文章介紹了線性表及其常見(jiàn)實(shí)現(xiàn)方式,包括順序表和鏈表,重點(diǎn)討論了順序表的實(shí)現(xiàn)細(xì)節(jié),如接口實(shí)現(xiàn)、增刪查改操作、內(nèi)存管理等,同時(shí),文章還簡(jiǎn)要介紹了ArrayList的概念及其在Java集合框架中的應(yīng)用,包括ArrayList的構(gòu)造、常見(jiàn)方法和遍歷方式
    2025-12-12
  • druid連接泄露故障全面分析

    druid連接泄露故障全面分析

    這篇文章主要介紹了druid連接泄露故障全面分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 解決mapper自動(dòng)裝配識(shí)別不了,Could not autowire.No beans of‘UserMapper‘type found

    解決mapper自動(dòng)裝配識(shí)別不了,Could not autowire.No beans&

    文章介紹了在使用MyBatisX插件和MybatisPlus自動(dòng)生成代碼后,如何解決Spring Boot項(xiàng)目中自動(dòng)注入`UserMapper`時(shí)報(bào)錯(cuò)的問(wèn)題,主要方法包括在主配置類或啟動(dòng)類上添加`@MapperScan`注解,指定Mapper文件夾所在的包路徑,以及在Mapper類上添加`@Repository`注解
    2024-11-11
  • Spring教程之異常捕獲方式

    Spring教程之異常捕獲方式

    這篇文章主要介紹了Spring異常捕獲方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • Maven通過(guò)filtering標(biāo)簽讀取變量配置的三種方法

    Maven通過(guò)filtering標(biāo)簽讀取變量配置的三種方法

    在日常開(kāi)發(fā)中,我們大多都會(huì)有開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境等,不同環(huán)境的參數(shù)肯定不一樣,本文主要介紹了Maven通過(guò)filtering標(biāo)簽讀取變量配置的三種方法,感興趣的可以了解一下
    2024-03-03
  • RocketMq深入分析講解兩種削峰方式

    RocketMq深入分析講解兩種削峰方式

    當(dāng)上游調(diào)用下游服務(wù)速率高于下游服務(wù)接口QPS時(shí),那么如果不對(duì)調(diào)用速率進(jìn)行控制,那么會(huì)發(fā)生很多失敗請(qǐng)求,通過(guò)消息隊(duì)列的削峰方法有兩種,這篇文章主要介紹了RocketMq深入分析講解兩種削峰方式
    2023-01-01

最新評(píng)論

马山县| 新兴县| 兴义市| 普安县| 英德市| 云林县| 诸暨市| 柳林县| 松溪县| 大安市| 开鲁县| 波密县| 岚皋县| 独山县| 昭苏县| 德庆县| 孙吴县| 囊谦县| 蓬溪县| 新密市| 洪湖市| 巍山| 汉中市| 八宿县| 蓝山县| 分宜县| 嘉黎县| 滨海县| 县级市| 行唐县| 休宁县| 贵定县| 深水埗区| 喜德县| 昌吉市| 永康市| 体育| 安吉县| 咸丰县| 颍上县| 靖边县|