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

MyBatis ResultMap 完全指南:解決字段映射不匹配與複雜關聯查詢

     編輯:Java 綜合教學

MyBatis ResultMap 完全指南:解決字段映射不匹配與複雜關聯查詢

MyBatis 的自動映射機制(resultType)雖然方便,但要求數據庫列名與 Java 實體屬性名嚴格一致。現實開發中,下劃線命名 vs 駝峰命名、多表關聯查詢、嵌套結果集 等場景屢見不鮮,這時 <resultMap> 就是破局利器。本文從基礎配置到進階關聯映射,系統梳理 ResultMap 核心用法。

一、 為什麼需要 ResultMap?

  • 列名與屬性名不一致(如 user_name vs userName)
  • 查詢結果包含多個實體(一對一、一對多關聯)
  • 需要自定義類型轉換、構造方法注入、區分主鍵與普通列
  • 官方文檔明確指出:HashMap 無法良好描述領域模型,應使用 JavaBean/POJO

二、 基礎映射配置

<mapper namespace="com.example.dao.UserMapper">
    <!-- id: 唯一標譽;type: 目標實體全限定名或別名 -->
    <resultMap id="userResultMap" type="com.example.entity.User">
        <!-- id 標籤標識主鍵,對緩存與比較至關重要 -->
        <id property="id" column="user_id" />
        <result property="userName" column="user_name" />
        <result property="email" column="email" />
        <result property="createTime" column="create_time" />
    </resultMap>

    <select id="selectById" resultMap="userResultMap">
        SELECT user_id, user_name, email, create_time
        FROM sys_user
        WHERE user_id = #{id}
    </select>
</mapper>

核心子標籤解析

標籤用途關鍵屬性
<id>主鍵列映射(影響 equals/hashCode 與緩存鍵)property, column, javaType, typeHandler
<result>普通列映射同 id
<constructor>構造方法注入(不可變對象)<idArg>, <arg>
<association>一對一關聯對象javaType, resultMap, select (嵌套查詢)
<collection>一對多集合映射ofType, resultMap, select

三、 進階場景:多表關聯映射

1. 一對一:用戶 + 詳情表(嵌套結果映射)

<resultMap id="userDetailMap" type="User">
    <id property="id" column="u_id" />
    <result property="username" column="u_name" />
    <association property="profile" javaType="UserProfile">
        <id property="id" column="p_id" />
        <result property="avatar" column="p_avatar" />
        <result property="bio" column="p_bio" />
    </association>
</resultMap>

<select id="selectUserWithProfile" resultMap="userDetailMap">
    SELECT u.id u_id, u.username u_name,
           p.id p_id, p.avatar p_avatar, p.bio p_bio
    FROM sys_user u
    LEFT JOIN user_profile p ON u.id = p.user_id
    WHERE u.id = #{id}
</select>

2. 一對多:訂單 + 訂單項(嵌套結果映射)

<resultMap id="orderMap" type="Order">
    <id property="id" column="o_id" />
    <result property="orderNo" column="o_no" />
    <result property="totalAmount" column="o_total" />
    <collection property="items" ofType="OrderItem">
        <id property="id" column="i_id" />
        <result property="skuCode" column="i_sku" />
        <result property="quantity" column="i_qty" />
        <result property="price" column="i_price" />
    </collection>
</resultMap>

<select id="selectOrderWithItems" resultMap="orderMap">
    SELECT o.id o_id, o.order_no o_no, o.total_amount o_total,
           i.id i_id, i.sku_code i_sku, i.quantity i_qty, i.price i_price
    FROM t_order o
    LEFT JOIN t_order_item i ON o.id = i.order_id
    WHERE o.id = #{id}
</select>

四、 嵌套查詢(按需加載/避免巨大 SQL)

當關聯數據量大或邏輯複雜,可拆分為多條 SQL,通過 select 屬性引用:

<resultMap id="orderLazyMap" type="Order">
    <id property="id" column="id" />
    <collection property="items"
               select="com.example.dao.OrderItemMapper.selectByOrderId"
               column="id" />  <!-- column 將作為參數傳給嵌套查詢 -->
</resultMap>

注意:嵌套查詢默認開啟延遲加載(需全局 lazyLoadingEnabled=true),N+1 問題需權衡。

五、 常見坑與最佳實踐

  1. 主鍵必標 <id>:否則緩存、去重、實體比較失效。
  2. 列別名消除歧義:多表 JOIN 時,SELECT u.id AS u_id, p.id AS p_id 避免列名衝突。
  3. typeHandler 處理特殊類型:枚舉、LocalDateTime、JSON 字段配置對應 handler。
  4. 驼峰命名自動映射:開啟 mapUnderscoreToCamelCase=true 可省去大量 <result>,但關聯映射仍需手寫。
  5. resultMap 復用:通過 extends 屬性繼承基礎映射,減少重複。

六、 對比:resultType vs resultMap

維度resultTyperesultMap
適用場景列名=屬性名、單表、無關聯列名不一致、多表關聯、複雜類型轉換
開發效率極高(零配置)需編寫 XML,但可復用
運行性能略高(無解析開銷)可忽略差異
可維護性差(隱式依賴命名約定)優(顯式聲明映射關係)

ResultMap 是 MyBatis 將關係數據映射為豐富領域模型的核心橋樑。熟練掌握 <association>、<collection> 及嵌套查詢,能讓你在複雜業務場景下遊刃有餘,告別「手寫映射循環」的痛苦。

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