首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MyBatis 多表關聯查詢:將三表字段扁平化映射到單一 Bean 的實用技巧

     編輯:程式設計疑難解答

場景

三表關係:

  • 客戶流失表(外鍵) → 客戶信息表(主鍵) ← 訂單表(外鍵)
  • 需求:根據流失表關聯查詢信息表,再關聯訂單表,結果在流失介面展示。

推薦方案:扁平化 Bean + 手寫 SQL(最簡單、效能可控)

不使用 `` 複雜的 ``/`` 巢狀映射,而是**將三表所需字段全部 SELECT 出來,映射到一個包含所有字段的扁平 Bean**。

1. 扁平化 Bean

public class CustomerLossView {
    // 流失表字段
    private Long lossId;
    private String lossReason;
    private Date lossDate;

    // 客戶信息表字段
    private Long customerId;
    private String customerName;
    private String phone;
    private String email;

    // 訂單表字段(可能多筆,取最新/匯總/第一筆)
    private Long orderId;
    private Date orderDate;
    private BigDecimal orderAmount;
    private String orderStatus;

    // getter/setter/toString
}

2. Mapper XML:左連接 + 條件聚合

<select id="selectLossDetail" resultType="com.example.CustomerLossView">
  SELECT
    cl.id AS lossId,
    cl.reason AS lossReason,
    cl.loss_date AS lossDate,
    ci.id AS customerId,
    ci.name AS customerName,
    ci.phone,
    ci.email,
    o.id AS orderId,
    o.order_date AS orderDate,
    o.amount AS orderAmount,
    o.status AS orderStatus
  FROM customer_loss cl
  LEFT JOIN customer_info ci ON cl.customer_id = ci.id
  LEFT JOIN (
    -- 子查詢:每客戶取最新一筆訂單
    SELECT o1.*
    FROM orders o1
    JOIN (
      SELECT customer_id, MAX(order_date) AS max_date
      FROM orders
      GROUP BY customer_id
    ) o2 ON o1.customer_id = o2.customer_id AND o1.order_date = o2.max_date
  ) o ON ci.id = o.customer_id
  WHERE cl.id = #{lossId}
</select>

3. Java 調用

CustomerLossView view = lossMapper.selectLossDetail(lossId);
// 直接使用 view.getCustomerName(), view.getOrderAmount() 等

為什麼不推薦巢狀 resultMap?

痛點說明
配置極其繁瑣需定義 ``、``、``、``、``,層層嵌套,XML 膨脹。
N+1 查詢風險若配置不當(如 `select` 屬性),MyBatis 會對每筆主表記錄發起額外查詢,效能災難。
結果集重複行一對多關聯導致主表字段重複,需 `resultMap` 的 `id` 屬性去重,易出錯。
調試困難SQL 與映射分離,排查欄位不匹配、類型轉換失敗極其痛苦。

適用場景對比

方案適用場景優點缺點
扁平 Bean + 手寫 SQL報表、詳情頁、扁平化展示、字段固定SQL 可控、效能最優、映射零配置、調試直觀Bean 膨脹、一對多只能取單筆/聚合
巢狀 resultMap真正需要物件圖(如訂單+明細行集合)語義豐富、支援集合映射配置複雜、N+1 風險、調試難
多次查詢 + 記憶體組裝邏輯極其複雜、跨庫/跨服務解耦、單表查詢簡單多次往返、記憶體組裝代碼多

總結

對於「三表關聯、結果扁平展示」的典型報表/詳情需求,**扁平化 Bean + 精心寫的單條 SQL(含子查詢取最新訂單)是最高效、最易維護的方案**。避免過度使用 MyBatis 進階映射功能,除非業務真正需要深層物件圖。SQL 寫得好,映射自然簡單。

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