首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis 一對一關聯映射入門教學:resultMap 與 association 實戰

     編輯:Java 相關知識

MyBatis 一對一關聯映射核心技術詳解

MyBatis 的 <association> 標籤是實現一對一關聯映射的關鍵,支援巢狀結果映射與巢狀查詢兩種載入策略。本文透過「使用者-訂單」經典場景,完整示範從實體類設計、Mapper XML 配置、介面定義到測試驗證的全流程。

領域模型設計

// 用戶實體
public class User {
    private Long id;
    private String username;
    private Order order; // 一對一關聯
    // getter/setter
}

// 訂單實體
public class Order {
    private Long id;
    private String orderNo;
    private Double amount;
    // getter/setter
}

資料表結構

CREATE TABLE t_user (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50)
);

CREATE TABLE t_order (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT,
    order_no VARCHAR(32),
    amount DECIMAL(10,2),
    FOREIGN KEY (user_id) REFERENCES t_user(id)
);

策略一:巢狀結果映射 - 單次查詢完成 (推薦簡單場景)

<resultMap id="userOrderMap" type="com.example.User">
    <id property="id" column="user_id"/>
    <result property="username" column="username"/>
    <association property="order" javaType="com.example.Order">
        <id property="id" column="order_id"/>
        <result property="orderNo" column="order_no"/>
        <result property="amount" column="amount"/>
    </association>
</resultMap>

<select id="selectUserWithOrder" resultMap="userOrderMap">
    SELECT u.id AS user_id, u.username,
           o.id AS order_id, o.order_no, o.amount
    FROM t_user u
    LEFT JOIN t_order o ON u.id = o.user_id
    WHERE u.id = #{userId}
</select>

優點: 單次 SQL、無 N+1 問題、效能最佳。
缺點:結果集列名需別名避免衝突;關聯對象為 null 時仍建立空物件(可配合 notNullColumn 優化)。

策略二:巢狀查詢 - 延遲載入 (適合複雜/大物件關聯)

<resultMap id="userMap" type="com.example.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <association property="order" 
        column="id" 
        select="selectOrderByUserId" 
        fetchType="lazy"/>
</resultMap>

<select id="selectUser" resultMap="userMap">
    SELECT id, username FROM t_user WHERE id = #{id}
</select>

<select id="selectOrderByUserId" resultType="com.example.Order">
    SELECT id, order_no, amount FROM t_order WHERE user_id = #{userId}
</select>

關鍵配置: 全域啟用延遲載入 <setting name="lazyLoadingEnabled" value="true"/>。
優點: 按需查詢、避免載入巨大關聯物件。
缺點: 可能產生 N+1 查詢,需權衡。

Mapper 介面定義

public interface UserMapper {
    User selectUserWithOrder(Long userId); // 策略一
    User selectUser(Long id);              // 策略二
}

進階技巧與最佳實踐

場景建議策略關鍵配置
關聯表較小、頻繁同時存取巢狀結果 (JOIN)resultMap + association + 列別名
關聯表大、低頻存取巢狀查詢 (延遲載入)fetchType="lazy" + column 傳參
關聯可能為空兩者皆可association notNullColumn="order_id"
多層巢狀 (User→Order→Address)巢狀結果多層 association 巢狀

常見坑點避雷

  • 列名衝突: 必須使用 SQL 別名 (AS) 區分 user.id 與 order.id
  • 主鍵重複導致合併錯誤: resultMap 的 <id> 必須唯一標識根物件,關聯物件也需 <id>
  • 延遲載入失效: 檢查 lazyLoadingEnabled、aggressiveLazyLoading 設定,避免 toString/序列化觸發誤載入
  • 型別轉換: javaType 必須為完整限定類名或別名註冊

掌握 <association> 兩大核心策略與配置細節,即可靈活應對 MyBatis 一對一關聯映射的各種業務場景,在效能與維護性之間找到最佳平衡點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved