MyBatis結(jié)果集映射的實(shí)現(xiàn)示例
一、ResultMap 的定義
在當(dāng)今的軟件開發(fā)領(lǐng)域,MyBatis 作為一款優(yōu)秀的持久層框架,以其簡潔的配置和強(qiáng)大的功能,深受廣大開發(fā)者的喜愛。然而,在實(shí)際的項(xiàng)目開發(fā)中,我們常常會遇到數(shù)據(jù)模型與數(shù)據(jù)庫表結(jié)構(gòu)不一致的情況,這時就需要 MyBatis 的 resultMap 功能來幫助我們實(shí)現(xiàn)復(fù)雜的映射關(guān)系。想象一下,一個典型的業(yè)務(wù)場景:一個電商系統(tǒng)中的訂單表,其字段包括訂單ID、用戶ID、商品ID、訂單金額等。然而,在業(yè)務(wù)邏輯層,我們可能需要將訂單信息與對應(yīng)的用戶信息和商品信息結(jié)合起來,以便于進(jìn)行后續(xù)的業(yè)務(wù)處理。如果直接使用 MyBatis 的基本映射功能,我們只能獲取到訂單的基本信息,而無法獲取到與之關(guān)聯(lián)的用戶和商品信息。這時,ResultMap 就顯得尤為重要。
在 MyBatis 中,ResultMap 是核心概念之一,用于定義復(fù)雜映射關(guān)系的關(guān)鍵功能,它定義了 SQL 查詢結(jié)果與 Java 對象之間的映射關(guān)系。它允許開發(fā)者將數(shù)據(jù)庫表中的字段映射到實(shí)體類的屬性上,同時也可以實(shí)現(xiàn)多表聯(lián)合查詢,將多個表的數(shù)據(jù)映射到一個實(shí)體類中。通過 ResultMap,我們可以輕松地實(shí)現(xiàn)數(shù)據(jù)模型與數(shù)據(jù)庫表結(jié)構(gòu)之間的映射,從而簡化了數(shù)據(jù)訪問層的開發(fā)。
二、基本配置
在開發(fā)過程中,我們經(jīng)常會遇到數(shù)據(jù)庫表與實(shí)體類(Entity)結(jié)構(gòu)不一致的情況。例如,一個數(shù)據(jù)庫表可能包含多個字段,而實(shí)體類只包含其中的一部分。在這種情況下,如果直接使用 MyBatis 的自動映射功能,可能會導(dǎo)致數(shù)據(jù)丟失或錯誤。映射關(guān)系是 ResultMap 的核心概念,它定義了數(shù)據(jù)庫表字段與 Java 對象屬性之間的對應(yīng)關(guān)系。
| 標(biāo)簽 | 映射類型 | 簡要說明 |
|---|---|---|
| id | 主鍵映射 | 將數(shù)據(jù)庫中的主鍵字段映射到Java對象的屬性上,用于唯一標(biāo)識記錄 |
| result | 普通屬性映射 | 將數(shù)據(jù)庫中的普通字段映射到Java對象的屬性上 |
| association | 關(guān)聯(lián)映射 | 將查詢結(jié)果中的關(guān)聯(lián)對象映射到Java對象的屬性上 |
| collection | 集合映射 | 將查詢結(jié)果中的集合對象映射到Java對象的屬性上 |
| select | 查詢語句 | 定義查詢操作,指定查詢結(jié)果映射規(guī)則 |
| resultMap | 映射配置 | 定義查詢結(jié)果的映射規(guī)則,包括字段映射、關(guān)聯(lián)映射和集合映射 |
2.1 resultMap:結(jié)果映射
ResultMap 是 MyBatis 框架中用于將數(shù)據(jù)庫查詢結(jié)果映射為 Java 對象的一種配置,它定義了如何將查詢結(jié)果集中的列映射到 Java 對象的屬性上。通過 resultMap,我們可以自定義字段與實(shí)體類屬性的映射關(guān)系,從而實(shí)現(xiàn)靈活的數(shù)據(jù)轉(zhuǎn)換。
<resultMap id="BaseResultMap" type="com.lilith.entity.User"> <id column="id" property="id" /> <result column="user_name" property="userName" /> <result column="real_name" property="realName" /> <result column="sex" property="sex" /> </resultMap>
一個標(biāo)準(zhǔn)的 resultMap 配置通常包含以下核心屬性:
| 屬性 | 是否必須 | 簡要說明 |
|---|---|---|
| id | ? | 當(dāng)前命名空間中的唯一標(biāo)識符 |
| type | ? | 指定映射的目標(biāo) Java 類的全限定名或別名,指定 MyBatis 將查詢結(jié)果封裝成哪種類型的對象 |
| extends | 用于繼承其他resultMap,減少重復(fù)代碼并提高代碼的可維護(hù)性 | |
| autoMapping | 是否啟用自動映射功能。 如果開啟(默認(rèn)情況),自動將結(jié)果集中與 Java 對象屬性同名(或符合駝峰命名規(guī)則)的列進(jìn)行映射 若設(shè)置為 false,則關(guān)閉自動映射,必須顯式配置所有字段的映射關(guān)系 |
?? 根據(jù) MyBatis 的 DTD 約束,resultMap 元素內(nèi)的子元素必須按照特定順序排列:constructor ?? id ?? result ?? association ?? collection ?? discriminator。
2.2 id:主鍵映射
id 標(biāo)簽是 resultMap 中的一個重要屬性,用于指定實(shí)體類的主鍵字段,確保每次操作都能準(zhǔn)確找到對應(yīng)的實(shí)體對象。在查詢數(shù)據(jù)時,MyBatis 會將查詢結(jié)果中的主鍵值與實(shí)體類的主鍵字段進(jìn)行映射。id 屬性的配置對于正確實(shí)現(xiàn)結(jié)果映射至關(guān)重要,MyBatis 會用其值作為對象標(biāo)識,提升緩存效率和對象比較準(zhǔn)確性。
<id property="id" column="user_id" javaType="int" jdbcType="INTEGER" />
| 屬性 | 是否必須 | 簡要說明 |
|---|---|---|
| property | ? | 指定實(shí)體類中對應(yīng)的主鍵屬性 |
| column | ? | 指定數(shù)據(jù)庫表中的主鍵字段 |
| javaType | 指定Java對象屬性的數(shù)據(jù)類型 | |
| jdbcType | 指定SQL語句中占位符的JDBC類型 | |
| typeHandler | 實(shí)現(xiàn)Java類型與JDBC類型之間的自定義轉(zhuǎn)換邏輯 |
2.3 result:普通字段映射
ResultMap 是一個 XML 元素,通常包含了一個或多個 Result 元素,每個 Result 元素用于指定實(shí)體類中的非主鍵字段與數(shù)據(jù)庫表字段的映射關(guān)系。
<result property="name" column="user_name" javaType="String" jdbcType="VARCHAR" />
| 屬性 | 是否必須 | 簡要說明 |
|---|---|---|
| column | ? | 對應(yīng)數(shù)據(jù)庫中的字段名。如果 SQL 中使用了別名,這里需填寫別名 |
| property | ? | 對應(yīng) Java 實(shí)體類中的屬性名 |
| javaType | 一個 Java 類的全限定名,或一個類型別名 | |
| jdbcType | 指定數(shù)據(jù)庫列類型,避免類型轉(zhuǎn)換錯誤(如 NULL 值處理) | |
| typeHandler | 指定類型處理器,用于處理Java類型與數(shù)據(jù)庫類型之間的轉(zhuǎn)換 |
2.4 association:一對一關(guān)聯(lián)
一對一關(guān)聯(lián)是指一個實(shí)體類對應(yīng)數(shù)據(jù)庫中的一張表,而另一個實(shí)體類與第一個實(shí)體類存在一對一的關(guān)系。在 MyBatis 中,可以使用 ResultMap 的子標(biāo)簽 association 來實(shí)現(xiàn)一對一映射,允許我們在查詢一個對象時,同時獲取其關(guān)聯(lián)的對象。
<association property="address" javaType="Address" column="address_id" select="selectAddressById" />
| 屬性 | 是否必須 | 簡要說明 |
|---|---|---|
| property | ? | 指定映射到實(shí)體類中的對象屬性名稱 |
| column | ? | 指定數(shù)據(jù)庫表中對應(yīng)的字段名或列別名,該字段的值將作為參數(shù)傳遞給嵌套查詢 |
| javaType | 指定該屬性對應(yīng)的 Java 類型 | |
| jdbcType | ||
| select | 指定另一個映射查詢的 ID,MyBatis 會額外執(zhí)行該 SQL 語句獲取關(guān)聯(lián)對象的結(jié)果 | |
| resultMap | 指定關(guān)聯(lián)實(shí)體的映射配置 | |
| typeHandler | ||
| notNullColumn | 如果設(shè)置了該屬性,只有當(dāng)指定列的值為非 NULL 時才會執(zhí)行關(guān)聯(lián)查詢,用于優(yōu)化查詢效率 | |
| columnPrefix | 當(dāng)關(guān)聯(lián)表的列名與主表的列名沖突時,可以為關(guān)聯(lián)表的列名添加前綴以區(qū)分 | |
| resultSet | ||
| foreignColumn | ||
| autoMapping | 指定是否啟用自動映射。默認(rèn)為true,表示自動映射列到Java對象的屬性忽略大小寫 | |
| fetchType | 控制關(guān)聯(lián)數(shù)據(jù)的加載方式,可選值為 lazy(延遲加載)或 eager(積極加載) |
2.5 collection:一對多關(guān)聯(lián)
一對多關(guān)聯(lián)是指一個實(shí)體類對應(yīng)數(shù)據(jù)庫中的一張表,而另一個實(shí)體類與第一個實(shí)體類存在一對多的關(guān)系。在 MyBatis 中,可以使用 ResultMap 的子標(biāo)簽 collection 來實(shí)現(xiàn)一對多關(guān)聯(lián),允許我們在查詢一個對象時,同時獲取其關(guān)聯(lián)的集合對象。
<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
| 屬性 | 是否必須 | 簡要說明 |
|---|---|---|
| property | ? | 指定映射到實(shí)體類中的對象屬性名稱 |
| column | ? | 指定數(shù)據(jù)庫表中對應(yīng)的字段名(或列別名),該字段的值將作為參數(shù)傳遞給嵌套查詢 |
| ofType | 指定集合中元素的Java類型 | |
| jdbcType | 指定該屬性對應(yīng)的 Java 類型 | |
| select | 指定另一個映射查詢的 ID,MyBatis 會額外執(zhí)行該 SQL 語句獲取關(guān)聯(lián)對象的結(jié)果 | |
| resultMap | 指定集合中元素的映射配置 | |
| typeHandler | ||
| notNullColumn | 如果設(shè)置了該屬性,只有當(dāng)指定列的值為非 NULL 時才會執(zhí)行關(guān)聯(lián)查詢,用于優(yōu)化查詢效率。 | |
| columnPrefix | 當(dāng)關(guān)聯(lián)表的列名與主表的列名沖突時,可以為關(guān)聯(lián)表的列名添加前綴以區(qū)分 | |
| resultSet | ||
| foreignColumn | ||
| autoMapping | 指定是否啟用自動映射。默認(rèn)為true,表示自動映射列到Java對象的屬性忽略大小寫 | |
| fetchType | 控制關(guān)聯(lián)數(shù)據(jù)的加載方式,可選值為 lazy(延遲加載)或 eager(積極加載) |
三、基本用法
3.1 簡單映射
我們可以使用 resultMap 標(biāo)簽自定義結(jié)果集和實(shí)體類屬性的映射規(guī)則,假設(shè)有一個 User 類,其屬性與數(shù)據(jù)庫中的字段不完全對應(yīng),可以這樣定義 resultMap:
<!-- 1??、定義 resultMap -->
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="password" column="user_pwd"/>
</resultMap>
<!-- 2??、在查詢中引用 resultMap -->
<select id="selectUserById" resultMap="userResultMap" parameterType="int">
SELECT user_id, user_name, user_pwd FROM users WHERE user_id = #{id}
</select>這樣,無論字段名如何不同,MyBatis 都能根據(jù) resultMap 將數(shù)據(jù)正確賦值到 User 對象上。
3.2 多表查詢
有的時候需要查詢多張表的數(shù)據(jù)才可以得到我們想要的結(jié)果,為此,可以直接寫一個多表關(guān)聯(lián)的SQL進(jìn)行查詢,也可以分步進(jìn)行多次的查詢來拿到我們需要的結(jié)果。Mybatis 就提供了對應(yīng)的配置,可以讓我們?nèi)ジ奖愕倪M(jìn)行相應(yīng)的查詢和對應(yīng)的結(jié)果集處理。
關(guān)聯(lián)映射(一對一)
假設(shè)每個用戶都有一個詳細(xì)地址信息,這里的地址信息相對于用戶是一對一。在查詢用戶的同時查詢用戶的地址,可以在 resultMap 中配置如下:
<resultMap id="addressMap" type="org.dllwh.mybatis.model.Address">
<id property="id" column="addr_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
<result property="zipCode" column="zipCode"/>
</resultMap>
<resultMap id="userWithAddressMap" type="User">
<id property="id" column="id"/>
<result property="userName" column="userName"/>
<result property="nickName" column="nickName"/>
<!-- 一對一關(guān)聯(lián):使用 association 標(biāo)簽 -->
<association property="address" resultMap="addressMap" />
</resultMap>
<select id="selectUserWithAddress" resultMap="userWithAddressMap" parameterType="int">
select suu.*, a.* from sys_upms_user suu
left join address a on suu.id = a.user_id
where id = #{userId}
</select>如果有需要多表查詢的需求,也可以選擇用多次查詢的方式來查詢出想要的數(shù)據(jù),Mybatis 也提供了對應(yīng)的配置。例如獲取查詢用戶時,還需查詢出該用戶所具有的地址信息。我們可以選擇先查詢User表查詢用戶信息,然后在去查詢關(guān)聯(lián)的地址信息。
<!--
select屬性:指定用哪個查詢來查詢當(dāng)前屬性的數(shù)據(jù)
column屬性:設(shè)置當(dāng)前結(jié)果集中哪列的數(shù)據(jù)作為select屬性指定的查詢方法需要參數(shù)
-->
<resultMap id="userWithAddressMap" type="User">
<id property="id" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="password" column="user_pwd"/>
<!-- 關(guān)聯(lián)映射,通過 user_id 關(guān)聯(lián)地址 -->
<association property="address" column="id" select="selectAddressByUserId"/>
</resultMap>
<!-- 1??、根據(jù)userId查詢用戶 -->
<select id="selectUserWithAddress" resultMap="userWithAddressMap" parameterType="int">
SELECT user_id, user_name, user_pwd FROM users WHERE user_id = #{id}
</select>
<!-- 2??、根據(jù)userId查詢所具有的地址信息 -->
<!-- 定義查詢地址的 SQL -->
<select id="selectAddressByUserId" resultType="Address" parameterType="int">
SELECT addr_id AS id, street, city, zip_code AS zipCode FROM address WHERE user_id = #{userId}
</select>集合映射(一對多)
假設(shè)每個用戶可以有多個角色,兩個實(shí)體之間是一對多的關(guān)系。例如在查詢用戶的同時,還需要該用戶所具有的角色信息,可以在 resultMap 中配置如下:
<!--定義User基本屬性映射規(guī)則--> <resultMap id="userMap" type="org.dllwh.mybatis.model.SysUser"> <id property="id" column="id"/> <result property="username" column="username" /> <result property="age" column="age" /> <result property="address" column="address" /> <collection property="roles" resultMap="userRoleMap"/> </resultMap> <resultMap id="userRoleMap" type="org.dllwh.mybatis.model.SysRole" > <id property="id" column="roleId"/> <result property="roleName" column="roleName"/> <result property="roleCode" column="roleCode"/> </resultMap> <select id="getUserLst" resultMap="userMap"> SELECT suu.*, sur.* from sys_upms_user suu LEFT JOIN sys_upms_user_role suur on suur.userId = suu.id LEFT JOIN sys_upms_role sur on suur.roleId = sur.id </select>

3.3 類型處理器
在 MyBatis 框架中,結(jié)果映射(Result Mapping)是核心功能之一,它負(fù)責(zé)將數(shù)據(jù)庫查詢結(jié)果映射到 Java 對象的屬性上。類型處理器(Type Handler)是 MyBatis 提供的一種機(jī)制,用于處理 Java 類型與數(shù)據(jù)庫類型之間的轉(zhuǎn)換。類型處理器的工作原理是,當(dāng)MyBatis在執(zhí)行查詢操作時,會根據(jù)SQL語句的結(jié)果集類型,調(diào)用相應(yīng)的類型處理器進(jìn)行數(shù)據(jù)轉(zhuǎn)換。類型處理器內(nèi)部定義了轉(zhuǎn)換規(guī)則,將數(shù)據(jù)庫中的數(shù)據(jù)類型轉(zhuǎn)換為Java對象中的屬性類型。
public interface TypeHandler<T> {
// 將數(shù)據(jù)庫類型轉(zhuǎn)換為Java類型
T fromDatabaseType(Object databaseValue);
// 將Java類型轉(zhuǎn)換為數(shù)據(jù)庫類型
Object toDatabaseType(T javaObject);
}
在 MyBatis 配置文件中,類型處理器與數(shù)據(jù)庫類型映射是通過定義 typeHandler 屬性來實(shí)現(xiàn)。例如,將 VARCHAR 類型的數(shù)據(jù)庫字段映射到 Java 對象的 String 屬性:
<resultMap id="userResultMap" type="User"> <result column="name" property="name" typeHandler="com.example.MyCustomTypeHandler"/> </resultMap>
自定義類型處理器可以滿足特定業(yè)務(wù)需求,以下是一個簡單的自定義類型處理器示例:
public class MyCustomTypeHandler implements TypeHandler<String> {
@Override
public String fromDatabaseType(Object databaseValue) {
// 將數(shù)據(jù)庫類型轉(zhuǎn)換為Java類型
return (String) databaseValue;
}
@Override
public Object toDatabaseType(String javaObject) {
// 將Java類型轉(zhuǎn)換為數(shù)據(jù)庫類型
return javaObject;
}
}四、總結(jié)
MyBatis 的 resultMap 提供了強(qiáng)大而靈活的機(jī)制,使得開發(fā)者能夠精準(zhǔn)地控制 SQL 查詢結(jié)果與 Java 對象之間的映射關(guān)系。無論是簡單的單表查詢還是復(fù)雜的多表聯(lián)合查詢,通過合理設(shè)計(jì) resultMap,都能大幅提高數(shù)據(jù)訪問層代碼的可讀性、可維護(hù)性和性能。這種靈活性正是 MyBatis 被廣泛使用的重要原因之一,也為開發(fā)者在實(shí)際項(xiàng)目中處理復(fù)雜數(shù)據(jù)模型提供了極大便利。
到此這篇關(guān)于MyBatis結(jié)果集映射的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)MyBatis結(jié)果集映射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Jmeter跨線程組傳值調(diào)用實(shí)現(xiàn)圖解
這篇文章主要介紹了Jmeter跨線程組傳值調(diào)用實(shí)現(xiàn)圖解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
Springboot 配置屬性綁定實(shí)現(xiàn)方式詳解
本文詳細(xì)介紹了Spring Boot中的配置屬性綁定,包括使用@ConfigurationProperties注解進(jìn)行配置文件數(shù)據(jù)批量綁定,以及如何在JavaBean中定義配置屬性,感興趣的朋友跟隨小編一起看看吧2025-11-11
IDEA-SpringBoot項(xiàng)目Debug啟動不了(卡住不動)的原因分析
這篇文章主要介紹了IDEA-SpringBoot項(xiàng)目Debug啟動不了(卡住不動)的原因分析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
SpringBoot利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的可以了解一下2022-10-10
Java如何找出數(shù)組中重復(fù)的數(shù)字
這篇文章主要為大家詳細(xì)介紹了Java如何找出數(shù)組中重復(fù)的數(shù)字,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08
使用MyEclipse 開發(fā)struts2框架實(shí)現(xiàn)登錄功能(結(jié)構(gòu)教程)
這篇文章主要介紹了使用MyEclipse 開發(fā)struts2框架實(shí)現(xiàn)登錄功能(結(jié)構(gòu)教程)的相關(guān)資料,需要的朋友可以參考下2016-03-03
聊聊springmvc中controller的方法的參數(shù)注解方式
本篇文章主要介紹了聊聊springmvc中controller的方法的參數(shù)注解方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10

