欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MyBatis 延遲加載與緩存的實(shí)現(xiàn)

 更新時(shí)間:2025年05月19日 08:58:36   作者:lyrhhhhhhhh  
本文主要介紹了MyBatis 延遲加載與緩存的實(shí)現(xiàn)

一、延遲加載策略:按需加載,優(yōu)化性能

1. 延遲加載 vs 立即加載:核心區(qū)別

  • 立即加載:主查詢(如查詢用戶)執(zhí)行時(shí),主動(dòng)關(guān)聯(lián)加載關(guān)聯(lián)數(shù)據(jù)(如用戶的所有賬號(hào))。
    • 場(chǎng)景:多對(duì)一查詢(如賬號(hào)關(guān)聯(lián)用戶),需立即獲取關(guān)聯(lián)數(shù)據(jù)。
  • 延遲加載:主查詢執(zhí)行時(shí)暫不加載關(guān)聯(lián)數(shù)據(jù),僅當(dāng)程序訪問(wèn)關(guān)聯(lián)數(shù)據(jù)時(shí),再觸發(fā)子查詢。
    • 場(chǎng)景:一對(duì)多查詢(如用戶關(guān)聯(lián)多個(gè)賬號(hào)),減少初始查詢壓力。

舉個(gè)小例子: 

場(chǎng)景:查詢用戶信息時(shí)不立即加載其訂單,僅在需要查看訂單時(shí)再觸發(fā)查詢。
示例:電商用戶詳情頁(yè)先展示用戶姓名、地址,點(diǎn)擊 “查看訂單” 按鈕時(shí),才加載該用戶的訂單列表。 

 2. 多對(duì)一延遲加載實(shí)現(xiàn)(Account → User)

步驟解析:

1、定義關(guān)聯(lián)查詢:主查詢僅查賬號(hào)表,關(guān)聯(lián)用戶信息通過(guò)子查詢延遲加載。

<!-- 主查詢:僅查賬號(hào) -->
<select id="findAll" resultMap="accountMap">
  SELECT * FROM account
</select>

<!-- 子查詢:通過(guò)用戶ID查用戶信息 -->
<select id="findById" parameterType="int" resultType="User">
  SELECT * FROM user WHERE id = #{id}
</select>

2、配置延遲加載:通過(guò) association 標(biāo)簽指定子查詢路徑和參數(shù)。

<resultMap type="Account" id="accountMap">
  <association 
    property="user"          <!-- Account類(lèi)中的User屬性 -->
    javaType="User"          <!-- 關(guān)聯(lián)對(duì)象類(lèi)型 -->
    select="findById"        <!-- 子查詢方法名 -->
    column="uid"             <!-- 主查詢結(jié)果中用于關(guān)聯(lián)的列(賬號(hào)表的uid) -->
  />
</resultMap>

3、全局開(kāi)啟延遲加載:在 SqlMapConfig.xml 中配置。

<settings>
  <setting name="lazyLoadingEnabled" value="true"/>   <!-- 開(kāi)啟延遲加載 -->
  <setting name="aggressiveLazyLoading" value="false"/> <!-- 關(guān)閉積極加載(默認(rèn)會(huì)加載所有關(guān)聯(lián)數(shù)據(jù)) -->
</settings>

 測(cè)試驗(yàn)證:

@Test
public void testLazyLoading() {
  List<Account> accounts = accountMapper.findAll();
  for (Account account : accounts) {
    System.out.println("賬號(hào)金額:" + account.getMoney()); // 主查詢執(zhí)行時(shí)僅輸出金額
    System.out.println("用戶名稱(chēng):" + account.getUser().getUsername()); // 首次訪問(wèn)user時(shí)觸發(fā)子查詢
  }
}

 3. 一對(duì)多延遲加載實(shí)現(xiàn)(User → Accounts)

 核心配置:

<!-- 主查詢:僅查用戶表 -->
<select id="findAll" resultMap="userMap">
  SELECT * FROM user
</select>

<resultMap type="User" id="userMap">
  <collection 
    property="accounts"       <!-- User類(lèi)中的賬號(hào)列表屬性 -->
    ofType="Account"          <!-- 集合元素類(lèi)型 -->
    select="com.qcbyjy.mapper.AccountMapper.findByUid" <!-- 子查詢:通過(guò)用戶ID查賬號(hào) -->
    column="id"                <!-- 主查詢結(jié)果中的用戶ID -->
  />
</resultMap>

<!-- 子查詢:根據(jù)用戶ID查賬號(hào) -->
<select id="findByUid" parameterType="int" resultType="Account">
  SELECT * FROM account WHERE uid = #{uid}
</select>

關(guān)鍵區(qū)別:

  • 多對(duì)一用 association(單個(gè)對(duì)象),一對(duì)多用 collection(集合)。
  • 子查詢參數(shù)通過(guò) column 傳遞主查詢結(jié)果中的字段(如用戶表的 id)。

 二、MyBatis 緩存機(jī)制:減少數(shù)據(jù)庫(kù)訪問(wèn)

 1. 緩存的核心價(jià)值

  • 定義:將頻繁查詢的數(shù)據(jù)臨時(shí)存儲(chǔ)在內(nèi)存中,避免重復(fù)訪問(wèn)數(shù)據(jù)庫(kù),提升查詢速度。
  • 適用場(chǎng)景:讀多寫(xiě)少、數(shù)據(jù)更新不頻繁的數(shù)據(jù)(如字典表、配置信息)。

 2. 一級(jí)緩存:SqlSession 級(jí)別的緩存

(1)本質(zhì)與作用

  • 作用域:基于 SqlSession 對(duì)象,同一 SqlSession 內(nèi)的相同查詢會(huì)直接從緩存獲取結(jié)果。
  • 實(shí)現(xiàn)原理SqlSession 內(nèi)部維護(hù)一個(gè) HashMap,鍵為查詢的唯一標(biāo)識(shí)(SQL + 參數(shù)),值為查詢結(jié)果對(duì)象。

(2)驗(yàn)證一級(jí)緩存

@Test
public void testFirstLevelCache() {
  // 同一 SqlSession 內(nèi)的兩次相同查詢
  User user1 = userMapper.findById(1);
  User user2 = userMapper.findById(1); // 直接從緩存獲取,不執(zhí)行 SQL
  System.out.println(user1 == user2); // 輸出 true(對(duì)象引用相同)
}

(3)緩存失效場(chǎng)景

  • SqlSession 關(guān)閉或提交(commit)。
  • 執(zhí)行 update/insert/delete 操作(會(huì)清空緩存)。
  • 手動(dòng)調(diào)用 session.clearCache() 清空緩存。

 3. 二級(jí)緩存:SqlSessionFactory 級(jí)別的緩存

(1)核心概念

  • 作用域:基于 SqlSessionFactory,跨 SqlSession 共享緩存(如多個(gè) SqlSession 執(zhí)行相同查詢)。
  • 實(shí)現(xiàn)條件

    實(shí)體類(lèi)需實(shí)現(xiàn) Serializable 接口(支持序列化存儲(chǔ))。

    在 SqlMapConfig.xml 中開(kāi)啟二級(jí)緩存(默認(rèn)已開(kāi)啟)。

    在 Mapper 中配置 <cache/> 標(biāo)簽。

(2)配置步驟

1、 實(shí)體類(lèi)實(shí)現(xiàn)序列化

public class User implements Serializable {
  // 省略屬性和方法
}

2、Mapper 中啟用緩存

<mapper namespace="com.qcbyjy.mapper.UserMapper">
  <cache/> <!-- 啟用二級(jí)緩存 -->
  
  <select id="findById" resultType="User" useCache="true">
    SELECT * FROM user WHERE id = #{id}
  </select>
</mapper>

3、配置緩存策略(可選)

<cache 
  eviction="LRU"       <!-- 緩存淘汰策略:LRU(最近最少使用) -->
  flushInterval="60000" <!-- 自動(dòng)刷新間隔(毫秒) -->
  size="512"           <!-- 最大緩存對(duì)象數(shù) -->
  readOnly="true"      <!-- 是否只讀:true(共享對(duì)象)/ false(復(fù)制對(duì)象) -->
/>

(3)緩存優(yōu)先級(jí)與刷新

  • 優(yōu)先級(jí):二級(jí)緩存 > 一級(jí)緩存 > 數(shù)據(jù)庫(kù)查詢。
  • 刷新機(jī)制:執(zhí)行 update/insert/delete 時(shí),會(huì)清空對(duì)應(yīng) Mapper 的二級(jí)緩存。

(4)測(cè)試驗(yàn)證

@Test
public void testSecondLevelCache() {
  try (SqlSession session1 = factory.openSession()) {
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    User user1 = mapper1.findById(1); // 首次查詢,命中數(shù)據(jù)庫(kù)
  }

  try (SqlSession session2 = factory.openSession()) {
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    User user2 = mapper2.findById(1); // 第二次查詢,命中二級(jí)緩存,不執(zhí)行 SQL
  }
}

 三、總結(jié):性能優(yōu)化核心要點(diǎn)

技術(shù)核心作用關(guān)鍵配置
延遲加載減少初始查詢數(shù)據(jù)量,提升響應(yīng)速度lazyLoadingEnabledassociation/collection 的 select 屬性
一級(jí)緩存減少同一會(huì)話內(nèi)的重復(fù)查詢自動(dòng)生效,無(wú)需額外配置(注意 SqlSession 生命周期)
二級(jí)緩存跨會(huì)話共享緩存,減少數(shù)據(jù)庫(kù)壓力實(shí)體類(lèi)序列化、<cache/> 標(biāo)簽、緩存策略配置

合理運(yùn)用延遲加載和緩存,能顯著提升 MyBatis 應(yīng)用的性能,但需根據(jù)業(yè)務(wù)場(chǎng)景靈活選擇,避免過(guò)度使用導(dǎo)致數(shù)據(jù)不一致或內(nèi)存溢出。

到此這篇關(guān)于MyBatis 延遲加載與緩存的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MyBatis 延遲加載與緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)合并圖片的方法示例

    java實(shí)現(xiàn)合并圖片的方法示例

    這篇文章主要介紹了java實(shí)現(xiàn)合并圖片的方法,結(jié)合具體實(shí)例形式分析了java基于圖片的讀取、設(shè)置、生成等操作實(shí)現(xiàn)圖片合并功能的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-02-02
  • mybatis中注解與xml配置的對(duì)應(yīng)關(guān)系和對(duì)比分析

    mybatis中注解與xml配置的對(duì)應(yīng)關(guān)系和對(duì)比分析

    這篇文章主要介紹了mybatis中注解與xml配置的對(duì)應(yīng)關(guān)系和對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • PowerMockito的基本使用解析

    PowerMockito的基本使用解析

    這篇文章主要介紹了PowerMockito的基本使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java?事務(wù)注解@Transactional回滾(try?catch、嵌套)問(wèn)題

    Java?事務(wù)注解@Transactional回滾(try?catch、嵌套)問(wèn)題

    這篇文章主要介紹了Java?@Transactional回滾(try?catch、嵌套)問(wèn)題,Spring?事務(wù)注解?@Transactional?本來(lái)可以保證原子性,如果事務(wù)內(nèi)有報(bào)錯(cuò)的話,整個(gè)事務(wù)可以保證回滾,但是加上try?catch或者事務(wù)嵌套,可能會(huì)導(dǎo)致事務(wù)回滾失敗
    2022-08-08
  • MyBatis-plus中的模糊查詢解讀

    MyBatis-plus中的模糊查詢解讀

    這篇文章主要介紹了MyBatis-plus中的模糊查詢解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Java中int和Integer的區(qū)別

    Java中int和Integer的區(qū)別

    這篇文章主要介紹的是?Java中int和Integer的區(qū)別,Java?是一種強(qiáng)數(shù)據(jù)類(lèi)型的語(yǔ)言,因此所有的屬性必須有一個(gè)數(shù)據(jù)類(lèi)型,下面文章基于Java詳細(xì)int和Integer有何區(qū)別,需要的朋友可以參考一下
    2021-11-11
  • Java深入解析接口interface

    Java深入解析接口interface

    接口是Java中最重要的概念之一,它可以被理解為一種特殊的類(lèi),不同的是接口的成員沒(méi)有執(zhí)行體,是由全局常量和公共的抽象方法所組成,本文給大家介紹Java接口,感興趣的朋友一起看看吧
    2022-06-06
  • Spring Bean生命周期之Bean的注冊(cè)詳解

    Spring Bean生命周期之Bean的注冊(cè)詳解

    這篇文章主要為大家詳細(xì)介紹了Spring Bean生命周期之Bean的注冊(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • 基于SpringBoot創(chuàng)建Web頁(yè)面并熱更新的操作步驟

    基于SpringBoot創(chuàng)建Web頁(yè)面并熱更新的操作步驟

    SpringBoot是一個(gè)用于快速開(kāi)發(fā)單個(gè)微服務(wù)的框架,它基于 Spring 框架,簡(jiǎn)化了Spring應(yīng)用的初始化過(guò)程和開(kāi)發(fā)流程,本文給大家介紹了如何基于SpringBoot創(chuàng)建Web頁(yè)面并熱更新,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • java 鍵盤(pán)輸入的多種實(shí)現(xiàn)方法

    java 鍵盤(pán)輸入的多種實(shí)現(xiàn)方法

    java不像C中擁有scanf這樣功能強(qiáng)大的函數(shù),大多是通過(guò)定義輸入輸出流對(duì)象。常用的類(lèi)有BufferedReader,Scanner。
    2013-03-03

最新評(píng)論