MyBatis映射文件 <resultMap> 元素詳解與示例


引言

<resultMap> 是 MyBatis 中最核心的映射配置元素,用于解決數據庫字段與 Java 對象屬性之間的復雜映射問題,尤其是字段名不一致、嵌套對象關聯、集合映射等場景。ResultMap 的設計思想是,對簡單的語句做到零配置,對于復雜一點的語句,只需要描述語句之間的關系就行了。以下是 <resultMap> 的詳細解析和用法說明。


一、<resultMap> 基礎結構

1. 核心屬性
  • id:唯一標識符,用于其他操作引用此映射。
  • type:映射的目標 Java 對象類型(全限定類名或別名)。
  • autoMapping:是否啟用自動映射(默認 false,建議部分場景開啟)。
    在這里插入圖片描述
2. 基礎示例

場景:數據庫字段為 user_id,Java 對象屬性為 userId

<!-- 
用戶結果映射(基礎版本)
功能:將數據庫查詢結果映射到com.example.User對象
說明:1. id="BaseUserMap":標識這個結果映射的唯一名稱。2. type="com.example.User":指定目標Java對象的完整類路徑。3. <id property="userId" column="user_id">:定義主鍵屬性userId與數據庫列user_id的映射關系。4. <result property="userName" column="user_name">:定義普通屬性userName與數據庫列user_name的映射關系。5. <result property="age" column="age">:定義普通屬性age與數據庫列age的映射關系。
用法:在需要復雜映射的場景下,可復用此結果映射。-->
<resultMap id="BaseUserMap" type="com.example.User"><id property="userId" column="user_id" /><result property="userName" column="user_name" /><result property="age" column="age" />
</resultMap><!-- 
查詢用戶基本信息
功能:從users表中查詢user_id、user_name和age列,并使用BaseUserMap結果映射轉換為Java對象
說明:1. id="getUser":標識這個查詢操作的唯一名稱。2. resultMap="BaseUserMap":指定使用BaseUserMap結果映射來處理查詢結果。3. SELECT user_id, user_name, age FROM users:從users表中查詢指定列。
用法:在Mapper接口中定義對應的方法,例如:User getUser();返回一個包含用戶基本信息的User對象。-->
<select id="getUser" resultMap="BaseUserMap">SELECT user_id, user_name, age FROM users
</select>

二、字段映射詳解

1. <id><result> 的區別
  • <id>:標記主鍵字段,影響緩存和性能優化(必須配置)。
  • <result>:普通字段映射。
    在這里插入圖片描述
2. 顯式映射 vs 自動映射
  • 顯式映射:手動配置所有字段(推薦復雜場景)。
  • 自動映射:開啟 autoMapping="true" 后,未配置的字段按名稱自動映射。
<!-- 
自動映射主鍵的用戶結果映射
功能:使用MyBatis的自動映射功能,將數據庫查詢結果映射到User對象
特別說明:1. autoMapping="true":表示開啟MyBatis的自動映射功能。- MyBatis會自動將查詢結果中與User對象屬性名匹配的列映射到對應的屬性上。2. <id property="userId" column="user_id">:手動配置主鍵映射,確保主鍵列與User對象的userId屬性正確對應。- 通常主鍵列需要顯式定義,其他非主鍵列可以依賴自動映射完成。-->
<resultMap id="AutoUserMap" type="User" autoMapping="true"><id property="userId" column="user_id" /> <!-- 只需配置主鍵 -->
</resultMap><!-- 
查詢用戶信息(使用自動映射)
功能:從users表中查詢所有用戶信息,并通過AutoUserMap結果映射轉換為User對象。
特別說明:- 該查詢語句只需簡單地從表中選擇所有列(SELECT *),因為開啟了自動映射,MyBatis會自動處理列名與User對象屬性的映射。- 如果某些列名與User對象屬性名不一致,可以手動在resultMap中配置對應的映射關系。-->
<select id="getUser" parameterType="String" resultMap="AutoUserMap">SELECT * FROM users
</select>

三、關聯關系映射

1. 一對一關聯 <association>

場景:用戶(User)與身份證(IDCard)一對一關聯。
Java 對象

public class User {private Integer userId;private String userName;private IDCard idCard; // 一對一對象
}

映射配置

<!-- 
用戶與身份證信息的結果映射
功能:將用戶信息和其關聯的身份證信息映射到User對象
說明:1. id="UserWithIDCardMap":標識這個結果映射的唯一名稱。2. type="User":指定目標Java對象類型為User。3. <id property="userId" column="user_id">:定義User對象的userId屬性與數據庫表的user_id列對應,作為主鍵。4. <result property="userName" column="user_name">:定義User對象的userName屬性與數據庫表的user_name列對應。5. <association property="idCard" javaType="IDCard">- property="idCard":User對象中的idCard屬性,表示用戶的身份證信息。- javaType="IDCard":指定關聯對象的Java類型為IDCard。- <id property="cardId" column="card_id">:定義IDCard對象的cardId屬性與數據庫表的card_id列對應,作為主鍵。- <result property="cardNumber" column="card_number">:定義IDCard對象的cardNumber屬性與數據庫表的card_number列對應。- 通過這個關聯映射,可以將用戶的身份證信息嵌套到User對象中。-->
<resultMap id="UserWithIDCardMap" type="User"><id property="userId" column="user_id"/><result property="userName" column="user_name"/><!-- 嵌套對象映射 --><association property="idCard" javaType="IDCard"><id property="cardId" column="card_id"/><result property="cardNumber" column="card_number"/></association>
</resultMap><!-- 
查詢用戶及其身份證信息
功能:從users和id_card表中查詢用戶及身份證數據,并通過UserWithIDCardMap結果映射轉換為Java對象
說明:1. id="getUserWithIDCard":標識這個查詢操作的唯一名稱。2. resultMap="UserWithIDCardMap":指定使用UserWithIDCardMap結果映射來處理查詢結果。3. SELECT u.user_id, u.user_name, c.card_id, c.card_number FROM users u LEFT JOIN id_card c ON u.user_id = c.user_id:- 查詢users表和id_card表的聯合數據。- LEFT JOIN將users表和id_card表連接,連接條件為用戶ID(u.user_id = c.user_id)。- 查詢結果將包含用戶的基本信息和其關聯的身份證信息。
用法:在Mapper接口中定義對應的方法,例如:User getUserWithIDCard();返回一個包含用戶及其身份證信息的User對象。-->
<select id="getUserWithIDCard" resultMap="UserWithIDCardMap">SELECT u.user_id, u.user_name, c.card_id, c.card_numberFROM users uLEFT JOIN id_card c ON u.user_id = c.user_id
</select>

2. 一對多關聯 <collection>

場景:用戶(User)與訂單(Order)一對多關聯。
Java 對象

public class User {private Integer userId;private String userName;private List<Order> orders; // 一對多集合
}

映射配置

<!-- 
用戶與訂單的結果映射
功能:將用戶信息及其關聯的訂單信息映射到User對象
說明:1. id="UserWithOrdersMap":標識這個結果映射的唯一名稱。2. type="User":指定目標Java對象類型為User。3. <id property="userId" column="user_id">:定義User對象的userId屬性與數據庫表的user_id列對應,作為主鍵。4. <result property="userName" column="user_name">:定義User對象的userName屬性與數據庫表的user_name列對應。5. <collection property="orders" ofType="Order">- property="orders":User對象中的orders屬性,表示用戶的訂單集合。- ofType="Order":指定集合中元素的類型為Order。- <id property="orderId" column="order_id">:定義Order對象的orderId屬性與數據庫表的order_id列對應,作為主鍵。- <result property="orderNo" column="order_no">:定義Order對象的orderNo屬性與數據庫表的order_no列對應。- <result property="amount" column="amount">:定義Order對象的amount屬性與數據庫表的amount列對應。- 通過這個集合映射,可以將用戶的訂單信息作為嵌套集合封裝到User對象中。-->
<resultMap id="UserWithOrdersMap" type="User"><id property="userId" column="user_id"/><result property="userName" column="user_name"/><!-- 集合映射 --><collection property="orders" ofType="Order"><id property="orderId" column="order_id"/><result property="orderNo" column="order_no"/><result property="amount" column="amount"/></collection>
</resultMap><!-- 
查詢用戶及其訂單信息
功能:從users和orders表中查詢用戶及訂單數據,并通過UserWithOrdersMap結果映射轉換為Java對象
說明:1. id="getUserWithOrders":標識這個查詢操作的唯一名稱。2. resultMap="UserWithOrdersMap":指定使用UserWithOrdersMap結果映射來處理查詢結果。3. SELECT u.user_id, u.user_name, o.order_id, o.order_no, o.amount FROM users u LEFT JOIN orders o ON u.user_id = o.user_id:- 查詢users表和orders表的聯合數據。- LEFT JOIN將users表和orders表連接,連接條件為用戶ID(u.user_id = o.user_id)。- 查詢結果將包含用戶的基本信息和其關聯的訂單信息。
用法:在Mapper接口中定義對應的方法,例如:User getUserWithOrders();返回一個包含用戶及其訂單信息的User對象。-->
<select id="getUserWithOrders" resultMap="UserWithOrdersMap">SELECT u.user_id, u.user_name,o.order_id, o.order_no, o.amountFROM users uLEFT JOIN orders o ON u.user_id = o.user_id
</select>

四、高級用法

1. 繼承映射 (extends)

復用已有的 resultMap,避免重復配置。

<!-- 
基礎用戶結果映射
功能:定義了一個基礎的結果映射,包含用戶的基本字段(user_id 和 user_name)
說明:1. id="BaseUserMap":標識這個結果映射的唯一名稱。2. type="User":指定目標Java對象類型為User。3. <id property="userId" column="user_id">:定義User對象的userId屬性與數據庫表的user_id列對應,作為主鍵。4. <result property="userName" column="user_name">:定義User對象的userName屬性與數據庫表的user_name列對應。5. 這個基礎映射可以被其他映射繼承和擴展,避免重復定義公共字段。-->
<resultMap id="BaseUserMap" type="User"><id property="userId" column="user_id"/><result property="userName" column="user_name"/>
</resultMap><!-- 
擴展基礎用戶結果映射,添加新字段
功能:在基礎用戶映射的基礎上,添加一個新的字段(email)
說明:1. id="ExtendedUserMap":標識這個結果映射的唯一名稱。2. extends="BaseUserMap":表示繼承BaseUserMap中的所有字段和配置。3. type="User":指定目標Java對象類型為User。4. <result property="email" column="email">:新增字段,定義User對象的email屬性與數據庫表的email列對應。5. 通過繼承基礎映射,可以避免重復定義公共字段,簡化配置。-->
<resultMap id="ExtendedUserMap" extends="BaseUserMap" type="User"><result property="email" column="email"/>
</resultMap>

2. 構造函數映射 <constructor>

通過構造方法注入字段(適合不可變對象)。
Java 對象

public class User {private final Integer userId;private final String userName;public User(Integer userId, String userName) {this.userId = userId;this.userName = userName;}
}

映射配置

<!-- 
用戶結果映射(基于構造函數)
功能:將數據庫查詢結果通過構造函數映射到User對象
說明:1. id="UserConstructorMap":標識這個結果映射的唯一名稱。2. type="User":指定目標Java對象類型為User。3. <constructor>:表示將通過User類的構造函數來初始化對象。4. <arg column="user_id" javaType="int">:- 定義構造函數的第一個參數,對應數據庫列user_id,Java類型為int。5. <arg column="user_name" javaType="String">:- 定義構造函數的第二個參數,對應數據庫列user_name,Java類型為String。6. 這個結果映射要求User類有一個接受兩個參數(int user_id, String user_name)的構造函數。
用法:在需要使用構造函數映射的場景下,通過這個resultMap將查詢結果轉換為User對象。-->
<resultMap id="UserConstructorMap" type="User"><constructor><arg column="user_id" javaType="int"/><arg column="user_name" javaType="String"/></constructor>
</resultMap>

3. 嵌套查詢(分步查詢)

解決關聯查詢的 N+1 性能問題,通過分步加載數據。

<!-- 
用戶與訂單的延遲加載映射 先查用戶,再通過 user_id 查訂單
功能:定義了一個結果映射,用于將用戶信息和其關聯的訂單信息進行映射。在查詢用戶時,不會立即加載訂單信息,而是通過延遲加載的方式在需要時再加載。
說明:1. id="UserWithLazyOrdersMap":標識這個結果映射的唯一名稱。2. type="User":指定目標Java對象類型為User。3. <id property="userId" column="user_id">:定義User對象的userId屬性與數據庫表的user_id列對應,作為主鍵。4. <result property="userName" column="user_name">:定義User對象的userName屬性與數據庫表的user_name列對應。5. <collection property="orders" ofType="Order" select="com.example.OrderMapper.getOrdersByUserId" column="user_id">- property="orders":User對象中的orders屬性,表示用戶關聯的訂單集合。- ofType="Order":指定集合中元素的類型為Order。- select="com.example.OrderMapper.getOrdersByUserId":指定一個單獨的SQL查詢語句,用于根據用戶ID查詢訂單信息。- column="user_id":將查詢結果中的user_id列作為參數傳遞給子查詢。-->
<resultMap id="UserWithLazyOrdersMap" type="User"><id property="userId" column="user_id"/><result property="userName" column="user_name"/><collection property="orders" ofType="Order"select="com.example.OrderMapper.getOrdersByUserId"column="user_id"/> <!-- 將 user_id 作為參數傳遞給子查詢 -->
</resultMap><!-- 
查詢用戶信息(延遲加載訂單)
功能:根據用戶ID查詢用戶的基本信息,并通過延遲加載的方式獲取其關聯的訂單信息。
說明:1. id="getUser":標識這個查詢操作的唯一名稱。2. resultMap="UserWithLazyOrdersMap":指定使用UserWithLazyOrdersMap結果映射來處理查詢結果。3. SELECT user_id, user_name FROM users WHERE user_id = #{id}:- 查詢users表中的user_id和user_name列。- WHERE user_id = #{id}:根據傳入的用戶ID進行查詢。
用法:在Mapper接口中定義對應的方法,例如:User getUser(int id);返回一個包含用戶基本信息的User對象,其orders屬性在需要時才會加載。-->
<select id="getUser" resultMap="UserWithLazyOrdersMap">SELECT user_id, user_name FROM users WHERE user_id = #{id}
</select>

OrderMapper.xml

<!-- 
根據用戶ID查詢訂單信息
功能:從orders表中查詢指定用戶的所有訂單
參數:userId(用戶ID)
返回:Order對象的列表,包含該用戶的所有訂單信息
說明:1. id="getOrdersByUserId":標識這個查詢操作的唯一名稱。2. resultType="Order":指定查詢結果的類型為Order對象。3. SELECT * FROM orders WHERE user_id = #{userId}:- 查詢orders表中所有列的數據。- WHERE user_id = #{userId}:條件是訂單的user_id等于傳入的userId參數。
用法:在Mapper接口中定義對應的方法,例如:List<Order> getOrdersByUserId(int userId);調用時傳入用戶ID,返回該用戶的所有訂單信息。-->
<select id="getOrdersByUserId" resultType="Order">SELECT * FROM orders WHERE user_id = #{userId}
</select>

在這里插入圖片描述


五、常見問題與最佳實踐

  1. 主鍵必須配置<id> 影響緩存機制,未配置可能導致性能下降。
  2. 避免過度嵌套:復雜關聯建議使用分步查詢(嵌套查詢)減少單次 SQL 復雜度。
  3. 自動映射的取舍:簡單場景可開啟 autoMapping,復雜字段仍需顯式配置。
  4. 性能優化:一對多關聯使用懶加載(fetchType="lazy"),按需加載數據。

六、總結

拓展閱讀:MyBatis映射文件常用元素詳解與示例
官方文檔:MyBatis | XML 映射文件
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895476.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895476.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895476.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【xdoj離散數學上機】T283

遞歸函數易錯&#xff1a; 防止出現遞歸死循環&#xff01; 題目 題目&#xff1a;求誘導出的等價關系的關系矩陣 問題描述 給定有限集合上二元關系的關系矩陣&#xff0c;求由其誘導出的等價關系的關系矩陣。 輸入格式 第一行輸入n&#xff0c;表示矩陣為n階方陣&#xff0c…

WIN11上使用GraalVM打包springboot3項目為本地可執行文件exe

耐心肝才能成功 概念步驟概要詳細步驟一. GraalVM 17二. 安裝Visual Studio 2022三. 創建springboot四. IDEA最新版或者eclipse2025調試項目五. 打包exe 概念 springboot3生成的jar編譯成windows本地C文件&#xff0c;不再依賴JVM運行 WINDOW編譯較為復雜&#xff0c;限制條件…

【git-hub項目:YOLOs-CPP】本地實現01:項目構建

目錄 寫在前面 項目介紹 最新發布說明 Segmentation示例 功能特點 依賴項 安裝 克隆代碼倉庫 配置 構建項目 寫在前面 前面剛剛實現的系列文章: 【Windows/C++/yolo開發部署01】 【Windows/C++/yolo開發部署02】 【Windows/C++/yolo開發部署03】 【Windows/C++/yolo…

超越 DeepSeek V3 -->【Qwen2.5-Max】

&#x1f525; 先說明&#xff0c;不是廣子&#xff0c;不是廣子&#xff01;&#xff01;&#xff01;單純分享這個工具給大家&#xff0c;畢竟最近使用 DeepSeek 太容易崩了&#xff0c;每天深度思考一次之后就開始轉圈圈用不了&#xff0c;然后就找到了這個工具使用 一、前言…

python自動化測試之Pytest框架之YAML詳解以及Parametrize數據驅動!

一、YAML詳解 YAML是一種數據類型&#xff0c;它能夠和JSON數據相互轉化&#xff0c;它本身也是有很多數據類型可以滿足我們接口 的參數類型&#xff0c;擴展名可以是.yml或.yaml 作用&#xff1a; 1.全局配置文件 基礎路徑&#xff0c;數據庫信息&#xff0c;賬號信息&…

CentOS 7操作系統部署KVM軟件和創建虛擬機

CentOS 7.9操作系統部署KVM軟件和配置指南&#xff0c;包括如何創建一個虛擬機。 步驟 1: 檢查硬件支持 首先&#xff0c;確認您的CPU支持虛擬化技術&#xff0c;并且已在BIOS中啟用&#xff1a; egrep -c (vmx|svm) /proc/cpuinfo 如果輸出大于0&#xff0c;則表示支持虛擬…

日本 萬葉假名

萬葉假名&#xff08;まんようがな&#xff0c;Manyōgana&#xff09;是一種早期的日語書寫系統&#xff0c;主要用于《萬葉集》等古代文獻中。它的特點是完全使用漢字來表示日語的音&#xff0c;不考慮漢字的原意。可以將其視為平假名和片假名的前身。 記住是唐代的發音不是…

【鴻蒙HarmonyOS Next實戰開發】實現組件動態創建和卸載-優化性能

一、簡介 為了解決頁面和組件加載緩慢的問題&#xff0c;ArkUI框架引入了動態操作功能&#xff0c;支持組件的預創建&#xff0c;并允許應用在運行時根據實際需求動態加載和渲染組件。 這些動態操作包括動態創建組件&#xff08;即動態添加組件&#xff09;和動態卸載組件&am…

【未完待續】關于I-Cache的一些思考

前言 最近對計組重拾興趣&#xff0c;想到了一些問題&#xff0c;本來想著會不會存在一些漏洞的&#xff0c;但是查閱資料發現還是自己太年輕了&#xff0c;架構師們早就想到了這些問題。這里簡單記錄一些與 GPT 的對話。感興趣的同學可以自行思考或查閱資料學習 與 GPT 的對…

MongoDB 7 分片副本集升級方案詳解(上)

#作者&#xff1a;任少近 文章目錄 前言&#xff1a;Mongodb版本升級升級步驟環境1.1環境準備1.2standalone升級1.3分片、副本集升級 前言&#xff1a;Mongodb版本升級 在開始升級之前&#xff0c;請參閱 MongoDB下個版本中的兼容性變更文檔&#xff0c;以確保您的應用程序和…

AI前端開發:跨領域合作的新引擎

隨著人工智能技術的飛速發展&#xff0c;AI代碼生成器等工具的出現正深刻地改變著軟件開發的模式。 AI前端開發的興起&#xff0c;不僅提高了開發效率&#xff0c;更重要的是促進了跨領域合作&#xff0c;讓數據科學家、UI/UX設計師和前端工程師能夠更緊密地協同工作&#xff0…

前端開發所需參考文檔—重中之中

菜鳥教程&#xff1a;https://www.runoob.com/ W3C&#xff1a;https://www.w3school.com.cn/index.html MMDN&#xff1a;https://developer.mozilla.org/zh-CN/ Vue3&#xff1a;Vue.js - 漸進式 JavaScript 框架 | Vue.js 基本上所有的前端開發基礎都可以在其中找到參考…

DeepSeek 助力 Vue 開發:打造絲滑的返回頂部按鈕(Back to Top)

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄 Deep…

C++中接口與繼承的區別(自我學習用)

繼承&#xff08;Inheritance&#xff09;和 接口&#xff08;Interface&#xff09;是面向對象編程&#xff08;OOP&#xff09;中的兩種不同概念&#xff0c;雖然在 C 中沒有像 Java 那樣的 interface 關鍵字&#xff0c;但可以通過 純虛函數 來實現接口的概念。讓我們詳細比…

epoll的原理

Epoll是Linux系統中高效的I/O多路復用機制&#xff0c;廣泛應用于高并發服務器&#xff08;如Nginx、Redis&#xff09;。其核心原理在于事件驅動模型和高效數據結構設計&#xff0c;解決了傳統select/poll的性能瓶頸。以下從數據結構、工作流程、觸發模式等維度展開分析&#…

epoll_ctl的概念和使用案例

epoll_ctl 是 Linux 系統中 I/O 多路復用機制 epoll 的核心函數之一&#xff0c;用于管理 epoll 實例監控的文件描述符&#xff08;File Descriptor, FD&#xff09;。它負責向 epoll 實例注冊、修改或刪除需要監控的 FD 及其事件類型&#xff0c;是實現高性能網絡編程&#xf…

Java練習(20)

ps:練習來自力扣 給你一個 非空 整數數組 nums &#xff0c;除了某個元素只出現一次以外&#xff0c;其余每個元素均出現兩次。找出那個只出現了一次的元素。 你必須設計并實現線性時間復雜度的算法來解決此問題&#xff0c;且該算法只使用常量額外空間。 class Solution {pu…

Tetragon:一款基于eBPF的運行時環境安全監控工具

關于Tetragon Tetragon是一款基于eBPF的運行時環境安全監控工具&#xff0c;該工具可以幫助廣大研究人員檢測并應對安全重大事件&#xff0c;例如流程執行事件、系統調用活動、I/O活動&#xff08;包括網絡和文件訪問等&#xff09;。 在 Kubernetes 環境中使用時&#xff0c;…

1046. 最后一塊石頭的重量

文章目錄 1.題目[1046. 最后一塊石頭的重量](https://leetcode.cn/problems/last-stone-weight/description/)2.思路3.代碼 1.題目 1046. 最后一塊石頭的重量 有一堆石頭&#xff0c;每塊石頭的重量都是正整數。 每一回合&#xff0c;從中選出兩塊** 最重的** 石頭&#xff…

Qt多線程技術【線程池】:QRunnable 和 QThreadPool

在現代軟件開發中&#xff0c;尤其是在處理大量并發任務時&#xff0c;線程池技術是一種高效的解決方案。線程池不僅能提高程序的性能&#xff0c;還能有效管理線程的生命周期&#xff0c;避免頻繁的線程創建和銷毀所帶來的性能損失。本文將以Qt中的 QThreadPool 和 QRunnable …