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

MyBatis 高級映射實戰:一對多關聯查詢完整實現指南

     編輯:Java 相關知識

場景痛點:訂單-用戶-明細三表關聯查詢

電商系統中常見需求:查詢訂單信息,同時級聯獲取下單用戶詳情及訂單包含的多條明細記錄。傳統方案需多次查詢或手動拼裝,MyBatis 的 <resultMap> 配合 <collection> 標籤可一次 SQL 完成映射,且自動去重主表數據。

一、數據庫設計與 SQL 編寫

1. 表結構假設

  • orders:訂單主表(id, user_id, number, note...)
  • t_user:用戶表(id, name, address, birthday...)
  • orderdetail:訂單明細表(id, order_id, items_id...)

2. 關鍵 SQL:主表驅動左連接

SELECT 
    o.*, 
    u.address, u.name, u.birthday,
    od.id AS orderdetail_id, od.orderid, od.itemsid
FROM orders o
INNER JOIN t_user u ON o.userid = u.id
LEFT JOIN orderdetail od ON od.orderid = o.id;

關鍵點: 使用 LEFT JOIN 保證無明細訂單也能查出;給明細表字段起別名避免與主表字段衝突(如 od.id AS orderdetail_id)。

二、實體類設計:體現關聯關係

public class Orders {
    private int id;
    private String number;
    private Date dateTime;
    private String note;
    private int userId;
    
    // 關聯對象:一對一
    private User user;
    
    // 關聯集合:一對多
    private List<OrdersDetail> ordersDetails;
    
    // getter/setter 省略
}

三、Mapper 接口定義

public interface OrdersCustomMapper {
    /**
     * 一對多查詢:訂單 + 用戶 + 明細列表
     */
    List<Orders> findOrderAndOrderDetailResultMap();
}

四、核心映射配置:resultMap 詳解

<mapper namespace="com.djp.config.mapper.OrdersCustomMapper">

    <!-- 基礎映射:訂單 + 用戶 (一對一) -->
    <resultMap id="ordersUserResultMap" type="com.djp.pojo.Orders">
        <id column="id" property="id"/>
        <result column="note" property="note"/>
        <result column="dateTime" property="dateTime"/>
        <result column="number" property="number"/>
        <result column="userId" property="userId"/>
        
        <!-- 一對一關聯:association -->
        <association property="user" javaType="com.djp.pojo.User">
            <id column="id" property="id"/> <!-- 用戶表主鍵,去重關鍵 -->
            <result column="name" property="name"/>
            <result column="address" property="address"/>
            <result column="birthday" property="birthday"/>
        </association>
    </resultMap>

    <!-- 擴展映射:繼承基礎映射 + 一對多集合 -->
    <resultMap id="orderAndOrderDetailResultMap" type="com.djp.pojo.Orders" extends="ordersUserResultMap">
        <!-- 一對多關聯:collection -->
        <collection property="ordersDetails" ofType="com.djp.pojo.OrdersDetail">
            <id column="orderdetail_id" property="id"/> <!-- 明細主鍵,集合去重關鍵 -->
            <result column="orderid" property="orderId"/>
            <result column="itemsid" property="itemsId"/>
        </collection>
    </resultMap>

    <select id="findOrderAndOrderDetailResultMap" resultMap="orderAndOrderDetailResultMap">
        SELECT o.*, u.address, u.name, u.birthday,
               od.id AS orderdetail_id, od.orderid, od.itemsid
        FROM orders o
        INNER JOIN t_user u ON o.userid = u.id
        LEFT JOIN orderdetail od ON od.orderid = o.id
    </select>

</mapper>

五、核心機制深度解析

標籤屬性作用去重關鍵
<id>column結果集列名MyBatis 根據 <id> 指定的列值判斷對象唯一性,
相同值則合併為同一對象,實現主表去重
property映射到實體屬性
<association>property映射到實體的關聯對象屬性配合 <id> 實現一對一去重
<collection>property映射到實體的集合屬性配合 <id> 實現一對多去重,
同一訂單的多條明細聚合到同一 List
ofType集合泛型類型

六、測試驗證

@Test
public void testFindOrderAndOrderDetailResultMap() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    OrdersCustomMapper mapper = sqlSession.getMapper(OrdersCustomMapper.class);
    
    List<Orders> list = mapper.findOrderAndOrderDetailResultMap();
    for (Orders order : list) {
        System.out.println("訂單:" + order.getNumber() 
            + " | 用戶:" + order.getUser().getName()
            + " | 明細數:" + order.getOrdersDetails().size());
    }
}

預期輸出: 訂單不重複,每個訂單包含完整用戶信息與對應明細列表。

七、避坑指南

  1. 主鍵必配:主表、關聯對象、集合元素均需在 <id> 中指定唯一標識列,否則去重失效。
  2. 列別名衝突:多表同名列(如 id)必須起別名,並在映射中使用別名。
  3. extends 復用:基礎映射提取公共部分,擴展映射繼承,減少重複配置。
  4. 嵌套查詢替代方案:數據量極大時,考慮分步查詢(select 屬性)避免超大結果集,但會產生 N+1 問題。

掌握 resultMap 的 association 與 collection 組合,是 MyBatis 處理複雜關聯查詢的核心技能,能大幅減少樣板代碼,提升開發效率。

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