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

MyBatis 關(guān)聯(lián)查詢延遲加載實(shí)戰(zhàn)案例

 更新時(shí)間:2026年05月08日 15:21:35   作者:Java成神之路-  
本文介紹了MyBatis開發(fā)中一對(duì)多、一對(duì)一關(guān)聯(lián)查詢的配置方法,重點(diǎn)講解了resultMap、association、collection等核心標(biāo)簽的使用場(chǎng)景和用語法,并詳細(xì)解釋了延遲加載(fetchType屬性)的配置方法和執(zhí)行流程,最后總結(jié)了單表查詢、一對(duì)一關(guān)聯(lián)和一對(duì)多關(guān)聯(lián)的配置方法和注意事項(xiàng)

前言

在MyBatis開發(fā)中,單表查詢我們直接用resultType就能輕松搞定,但遇到一對(duì)多、一對(duì)一關(guān)聯(lián)查詢(如1個(gè)用戶對(duì)應(yīng)多個(gè)訂單、1個(gè)訂單對(duì)應(yīng)1個(gè)用戶),且需要優(yōu)化性能時(shí),就必須用到resultMap配合延遲加載。

一、核心基礎(chǔ)概念

1. 業(yè)務(wù)場(chǎng)景:一對(duì)多關(guān)系

最經(jīng)典的場(chǎng)景:用戶表(一) ↔ 訂單表(多)

  • 1個(gè)用戶可以擁有多個(gè)訂單
  • 1個(gè)訂單只屬于1個(gè)用戶

對(duì)應(yīng)Java實(shí)體類設(shè)計(jì):

// 用戶實(shí)體(一的一方)
@Data
public class User {
    private Integer id;
    private String username;
    // 一對(duì)多:存放當(dāng)前用戶的所有訂單
    private List<Order> orderList;
}
// 訂單實(shí)體(多的一方)
@Data
public class Order {
    private Integer id;
    private String orderNo;
    // 多對(duì)一:存放訂單所屬的用戶
    private User user;
}

2. 立即加載 VS 延遲加載(懶加載)

這是性能優(yōu)化的核心,也是配置fetchType="lazy"的意義:

加載方式含義優(yōu)缺點(diǎn)
立即加載查詢數(shù)據(jù)時(shí),同時(shí)查詢關(guān)聯(lián)數(shù)據(jù)代碼簡(jiǎn)單;查詢?nèi)哂?,性能?/td>
延遲加載查詢時(shí)只查本身數(shù)據(jù),用到關(guān)聯(lián)數(shù)據(jù)時(shí)才查詢減少冗余SQL,性能高;需要額外配置
通俗理解:延遲加載就是按需加載,用不到的數(shù)據(jù)絕不查詢!

二、為什么要寫 resultMap?(關(guān)聯(lián)查詢專用)

1. 單表查詢

日常單查用戶/訂單,一行代碼搞定,完全不用復(fù)雜配置:

<!-- 單表查詢:resultType 直接映射,無需配置resultMap -->
<select id="selectById" resultType="com.itheima.pojo.User">
    select * from tb_user where id = #{id}
</select>

? 適用場(chǎng)景:純單表查詢,無關(guān)聯(lián)關(guān)系

2. 必須用復(fù)雜配置的場(chǎng)景

當(dāng)需求變?yōu)椋?strong>查詢主數(shù)據(jù) + 按需加載關(guān)聯(lián)數(shù)據(jù)

MyBatis規(guī)定:一對(duì)多/一對(duì)一關(guān)聯(lián) + 延遲加載,必須使用 resultMap 配置

這是固定語法!

三、一對(duì)一延遲加載(association 標(biāo)簽)

一對(duì)一場(chǎng)景:訂單表 ↔ 用戶表(1個(gè)訂單只屬于1個(gè)用戶),MyBatis用association標(biāo)簽實(shí)現(xiàn)一對(duì)一延遲加載!

1. 一對(duì)一核心配置

<?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.itheima.mapper.OrderMapper">
    <!-- 一對(duì)一結(jié)果映射 -->
    <resultMap id="orderResultMap" type="order" autoMapping="true">
        <id property="id" column="id"/>
        <result property="orderNo" column="order_no"/>
        <!-- 一對(duì)一關(guān)聯(lián)配置:延遲加載用戶信息 -->
        <association
            property="user"
            javaType="user"
            select="com.itheima.mapper.UserMapper.selectById"
            column="user_id"
            fetchType="lazy">
        </association>
    </resultMap>
    <!-- 根據(jù)id查詢訂單 -->
    <select id="selectById" resultMap="orderResultMap">
        select * from tb_order where id = #{id}
    </select>
</mapper>

? association 標(biāo)簽5大核心屬性

  1. property:實(shí)體類中關(guān)聯(lián)對(duì)象屬性名(Order類中的user)
  2. javaType:關(guān)聯(lián)對(duì)象的實(shí)體類型
  3. select:延遲加載調(diào)用的查詢方法全路徑
  4. column:傳遞給子查詢的參數(shù)(訂單表的user_id)
  5. fetchType="lazy":開啟一對(duì)一延遲加載

四、一對(duì)多延遲加載(collection 標(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.itheima.mapper.UserMapper">
    <!-- 1. 定義復(fù)雜映射規(guī)則:id唯一標(biāo)識(shí),type映射實(shí)體類,autoMapping自動(dòng)匹配字段 -->
    <resultMap id="userResultMap" type="user" autoMapping="true">
        <!-- 2. 主鍵映射(規(guī)范寫法,可省略) -->
        <id property="id" column="id"/>
        <!-- 普通字段映射(autoMapping=true可自動(dòng)匹配,可省略) -->
        <result property="username" column="username"/>
        <!-- 3. 核心:一對(duì)多關(guān)聯(lián)映射,延遲加載配置 -->
        <collection
            property="orderList"
            ofType="order"
            select="com.itheima.mapper.OrderMapper.findByUid"
            column="id"
            fetchType="lazy">
        </collection>
    </resultMap>
    <!-- 4. 查詢用戶,綁定上面的映射規(guī)則 -->
    <select id="selectById" resultMap="userResultMap">
        select * from tb_user where id = #{id}
    </select>
</mapper>

? collection 標(biāo)簽5大核心屬性

這是一對(duì)多配置的靈魂,記住這5個(gè)屬性,再也不會(huì)寫錯(cuò):

  1. property:實(shí)體類中集合屬性的名稱(必須和User類中的orderList一致)
  2. ofType:集合中存儲(chǔ)的實(shí)體類型
  3. select:延遲加載時(shí)執(zhí)行的子查詢方法全路徑
  4. column:傳遞給子查詢的參數(shù)列(用戶id)
  5. fetchType="lazy"開啟延遲加載(默認(rèn)是立即加載)

五、完整實(shí)戰(zhàn)代碼

1. MyBatis全局配置(開啟延遲加載總開關(guān))

<settings>
    <!-- 開啟延遲加載總開關(guān) -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 關(guān)閉積極加載(3.4.1后默認(rèn)false,配置更保險(xiǎn)) -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

lazyLoadingEnabled(總開關(guān))

作用:控制 是否開啟延遲加載

默認(rèn)值:false → 關(guān)閉延遲加載,默認(rèn)使用立即加載

人話:查詢主數(shù)據(jù)時(shí),直接把關(guān)聯(lián)數(shù)據(jù)一起查出來,不等待調(diào)用

aggressiveLazyLoading(觸發(fā)方式)

作用:控制 延遲加載的觸發(fā)條件

默認(rèn)值:false

人話:只有開啟了延遲加載(lazyLoadingEnabled=true),這個(gè)配置才有用!

true:調(diào)用對(duì)象任何方法(toString/equals/getter)都觸發(fā)加載

false:只調(diào)用關(guān)聯(lián)屬性的 getter 方法才觸發(fā)加載(最標(biāo)準(zhǔn)的懶加載)

2. 子查詢Mapper配置

一對(duì)多/一對(duì)一依賴的子查詢方法必須單獨(dú)定義:

<mapper namespace="com.itheima.mapper.OrderMapper">
    <!-- 根據(jù)用戶id查詢訂單:供一對(duì)多延遲加載調(diào)用 -->
    <select id="findByUid" resultType="com.itheima.pojo.Order">
        select * from tb_order where user_id = #{userId}
    </select>
</mapper>

3. Mapper接口

// UserMapper
public interface UserMapper {
    User selectById(Integer id);
}
// OrderMapper
public interface OrderMapper {
    List<Order> findByUid(Integer userId);
    Order selectById(Integer id);
}

六、延遲加載執(zhí)行流程

1. 一對(duì)一執(zhí)行流程

@Test
public void testOneToOne(){
    // 1. 僅查詢訂單:只執(zhí)行1條SQL → select * from tb_order where id=1
    Order order = orderMapper.selectById(1);
    System.out.println("訂單編號(hào):" + order.getOrderNo());
    // 2. 調(diào)用user:觸發(fā)一對(duì)一延遲加載,查詢用戶信息
    System.out.println("訂單所屬用戶:" + order.getUser());
}

2. 一對(duì)多執(zhí)行流程

@Test
public void testLazyLoad(){
    // 1. 僅查詢用戶:只執(zhí)行1條SQL → select * from tb_user where id=1
    User user = userMapper.selectById(1);
    System.out.println("查詢到用戶:" + user.getUsername());
    // 2. 未使用訂單數(shù)據(jù):不執(zhí)行訂單查詢SQL
    // 3. 調(diào)用orderList:觸發(fā)延遲加載,執(zhí)行訂單SQL → select * from tb_order where user_id=1
    System.out.println("用戶訂單:" + user.getOrderList());
}

完美實(shí)現(xiàn)按需加載

七、注意事項(xiàng)

  1. 忘記開啟全局延遲加載
    全局開關(guān) lazyLoadingEnabled(默認(rèn) false)控制所有未顯式設(shè)置 fetchType 的關(guān)聯(lián); 局部屬性 fetchType="lazy" 可以獨(dú)立讓單個(gè)關(guān)聯(lián)延遲加載,不受全局開關(guān)影響。
  2. 子查詢方法不存在/路徑寫錯(cuò)
    select屬性必須是全限定名,因?yàn)檫@是兩個(gè)mapper.xml文件。
  3. 實(shí)體類屬性名不匹配
    配置的property屬性必須和實(shí)體類屬性名完全一致。
  4. 標(biāo)簽區(qū)分
    一對(duì)多用collection,一對(duì)一用association,不可混用!

八、延遲加載的優(yōu)勢(shì)

  • 提升性能:避免查詢不需要的關(guān)聯(lián)數(shù)據(jù),減少數(shù)據(jù)庫壓力
  • 解決N+1問題:查詢數(shù)據(jù)時(shí),不會(huì)自動(dòng)查詢關(guān)聯(lián)數(shù)據(jù)
  • 靈活適配業(yè)務(wù):只查主數(shù)據(jù)時(shí),無冗余SQL
  • 通用適配:同時(shí)支持一對(duì)多、一對(duì)一關(guān)聯(lián)場(chǎng)景

九、總結(jié)

  1. 單表查詢:用resultType,無需任何復(fù)雜配置(日常開發(fā)主流);
  2. 一對(duì)一關(guān)聯(lián):必須用resultMap + association;
  3. 一對(duì)多關(guān)聯(lián):必須用resultMap + collection
  4. 延遲加載核心fetchType="lazy" + 全局配置開關(guān) + 按需加載;
  5. 核心標(biāo)簽:association(一對(duì)一)、collection(一對(duì)多),語法結(jié)構(gòu)高度一致,僅標(biāo)簽和類型屬性不同。

到此這篇關(guān)于MyBatis 關(guān)聯(lián)查詢延遲加載案例的文章就介紹到這了,更多相關(guān)mybatis 延遲加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis分頁的四種方式

    MyBatis分頁的四種方式

    分頁查詢是非常常見的需求,本文主要介紹了MyBatis分頁的四種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Spring核心容器之ApplicationContext上下文啟動(dòng)準(zhǔn)備詳解

    Spring核心容器之ApplicationContext上下文啟動(dòng)準(zhǔn)備詳解

    這篇文章主要介紹了Spring核心容器之ApplicationContext上下文啟動(dòng)準(zhǔn)備詳解,ApplicationContext 繼承自 BeanFactory ,其不僅包含 BeanFactory 所有功能,還擴(kuò)展了容器功能,需要的朋友可以參考下
    2023-11-11
  • java實(shí)現(xiàn)可逆加密算法

    java實(shí)現(xiàn)可逆加密算法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)可逆加密算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • Spring Cloud體系實(shí)現(xiàn)標(biāo)簽路由的方法示例

    Spring Cloud體系實(shí)現(xiàn)標(biāo)簽路由的方法示例

    這篇文章主要介紹了Spring Cloud體系實(shí)現(xiàn)標(biāo)簽路由的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • MyBatis中的循環(huán)插入insert foreach問題

    MyBatis中的循環(huán)插入insert foreach問題

    這篇文章主要介紹了MyBatis中的循環(huán)插入insert foreach問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Java并發(fā)編程之Lock鎖機(jī)制從使用到源碼實(shí)現(xiàn)

    Java并發(fā)編程之Lock鎖機(jī)制從使用到源碼實(shí)現(xiàn)

    這篇文章主要介紹了Java并發(fā)編程之Lock鎖機(jī)制從使用到源碼實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2025-10-10
  • Java中ArrayList、Vector、LinkedList的核心區(qū)別與應(yīng)用場(chǎng)景詳解

    Java中ArrayList、Vector、LinkedList的核心區(qū)別與應(yīng)用場(chǎng)景詳解

    在Java編程語言中ArrayList、Vector和LinkedList是三個(gè)常見的列表實(shí)現(xiàn),它們都實(shí)現(xiàn)了List接口,這篇文章主要介紹了Java中ArrayList、Vector、LinkedList的核心區(qū)別與應(yīng)用場(chǎng)景的相關(guān)資料,需要的朋友可以參考下
    2025-07-07
  • Java基礎(chǔ)語法:邏輯控制

    Java基礎(chǔ)語法:邏輯控制

    下面小編就為大家?guī)硪黄狫ava邏輯控制的基礎(chǔ)文章。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-08-08
  • Java虛擬機(jī)裝載和初始化一個(gè)class類代碼解析

    Java虛擬機(jī)裝載和初始化一個(gè)class類代碼解析

    這篇文章的主要內(nèi)容是Java虛擬機(jī)裝載和初始化一個(gè)class類的代碼解析,包括介紹了裝載和初始化的時(shí)機(jī)與方式,需要的朋友可以參考下。
    2017-09-09
  • spring?boot前后端交互之?dāng)?shù)據(jù)格式轉(zhuǎn)換問題

    spring?boot前后端交互之?dāng)?shù)據(jù)格式轉(zhuǎn)換問題

    這篇文章主要介紹了spring?boot前后端交互之?dāng)?shù)據(jù)格式轉(zhuǎn)換,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01

最新評(píng)論

彰化县| 木兰县| 贺州市| 黄浦区| 黔东| 铅山县| 嘉义市| 瓦房店市| 奎屯市| 禹州市| 望谟县| 贵德县| 冀州市| 黑山县| 济阳县| 营口市| 宽甸| 敦煌市| 乃东县| 天峨县| 远安县| 休宁县| 西乌| 玉溪市| 大余县| 平乡县| 大足县| 闸北区| 惠水县| 连云港市| 宁强县| 茌平县| 日喀则市| 邵东县| 平定县| 玉山县| 万源市| 乐都县| 滦平县| 常熟市| 郯城县|