mybatis中resultMap的association及collectio的使用詳解
1.reusltmap的說明
resultmap定義了數(shù)據(jù)庫的結(jié)果映射到j(luò)ava對(duì)象的規(guī)則,resultmap包含4個(gè)屬性:
id
: ResultMap 的唯一標(biāo)識(shí)type
: 映射到的 Java 類型(全限定類名或別名)extends
: 繼承另一個(gè) ResultMapautoMapping
: 是否開啟自動(dòng)映射(true/false)
前三個(gè)比較常用
resultmap包含以下子元素,并且子元素是有定義順序的,如下:
<constructor>
(可選)<id>
(至少一個(gè))<result>
(零個(gè)或多個(gè))<association>
(零個(gè)或多個(gè))<collection>
(零個(gè)或多個(gè))<discriminator>
(可選)
必須遵循上述順序,如果順序不正確,MyBatis 在解析 XML 時(shí)會(huì)拋出異常
<id>
元素必須出現(xiàn)在<result>
元素之前- 如果使用
<constructor>
,它必須是第一個(gè)元素 <discriminator>
必須是最后一個(gè)元素(如果存在)
2.association的使用
<association>
是 MyBatis 中用于處理一對(duì)一關(guān)聯(lián)關(guān)系的元素,它可以將查詢結(jié)果中的一部分?jǐn)?shù)據(jù)映射到一個(gè)復(fù)雜的關(guān)聯(lián)對(duì)象中。
在實(shí)際開發(fā)中,如果想一次查詢兩張表的數(shù)據(jù),不想通過兩次查詢的方式,而是想一次查詢出來,可以通過兩張表關(guān)聯(lián)將表A和表B的數(shù)據(jù)都查詢出來
屬性名 | 說明 |
---|---|
property | Java對(duì)象中的屬性名 |
javaType | 關(guān)聯(lián)對(duì)象的Java類型(全限定類名或別名) |
resultMap | 引用外部定義的resultMap |
column | 傳遞給嵌套查詢的列名(可以是多個(gè)列:column="{prop1=col1,prop2=col2}") |
select | 另一個(gè)映射語句的ID,用于嵌套查詢 |
fetchType | 覆蓋全局的延遲加載設(shè)置(lazy/eager) |
autoMapping | 是否啟用自動(dòng)映射(true/false) |
<!-- 一對(duì)一關(guān)聯(lián)映射示例 --> <resultMap id="UserWithDeptMap" type="com.example.User"> <!-- 用戶表字段映射 --> <id column="user_id" property="id" jdbcType="BIGINT"/> <result column="user_name" property="name" jdbcType="VARCHAR"/> <result column="user_age" property="age" jdbcType="INTEGER"/> <!-- 一對(duì)一關(guān)聯(lián) department 對(duì)象 --> <association property="department" javaType="com.example.Department"> <id column="dept_id" property="id" jdbcType="BIGINT"/> <result column="dept_name" property="deptName" jdbcType="VARCHAR"/> <result column="dept_location" property="location" jdbcType="VARCHAR"/> </association> </resultMap>
<select id="selectUserWithDepartment" resultMap="UserWithDeptMap"> SELECT u.id AS user_id, u.name AS user_name, u.age AS user_age, d.id AS dept_id, d.name AS dept_name, d.location AS dept_location FROM user u LEFT JOIN department d ON u.dept_id = d.id WHERE u.id = #{userId} </select>
package com.example; public class User { private Long id; // 對(duì)應(yīng) user_id 字段 private String name; // 對(duì)應(yīng) user_name 字段 private Integer age; // 對(duì)應(yīng) user_age 字段 private Department department; // 一對(duì)一關(guān)聯(lián)對(duì)象 // 必須的 getter 和 setter 方法 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }
package com.example; public class Department { private Long id; // 對(duì)應(yīng) dept_id 字段 private String deptName; // 對(duì)應(yīng) dept_name 字段 private String location; // 對(duì)應(yīng) dept_location 字段 // 必須的 getter 和 setter 方法 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } }
使用關(guān)聯(lián)查詢只需要指定以下兩個(gè)屬性即可
配置項(xiàng) | 作用 |
property="department" | 指定 User 類中關(guān)聯(lián)屬性的名稱(需與字段名一致)。 |
javaType | 指定關(guān)聯(lián)對(duì)象的完整類名(可省略,MyBatis 通常能自動(dòng)推斷)。 |
3.collection的使用
<collection>
是 MyBatis 中用于處理一對(duì)多關(guān)聯(lián)關(guān)系的核心元素,它能夠?qū)⒉樵兘Y(jié)果中的多條記錄映射到一個(gè)集合屬性中(如 List、Set 等)
屬性名 | 是否必填 | 說明 |
---|---|---|
property | 必填 | Java對(duì)象中的集合屬性名稱 |
ofType | 條件必填 | 集合中元素的Java類型(當(dāng)不使用resultMap時(shí)必填) |
column | 條件必填 | 傳遞給嵌套查詢的列名(使用select時(shí)必填) |
select | 可選 | 另一個(gè)映射語句的ID,用于嵌套查詢 |
fetchType | 可選 | 加載方式(lazy/eager),覆蓋全局配置 |
javaType | 可選 | 集合的Java類型(如ArrayList、HashSet等) |
resultMap | 可選 | 引用外部定義的resultMap |
autoMapping | 可選 | 是否啟用自動(dòng)映射(true/false) |
<resultMap id="UserWithOrdersMap" type="com.example.model.User"> <id property="id" column="user_id"/> <result property="name" column="user_name"/> <result property="age" column="user_age"/> <!-- 一對(duì)多關(guān)聯(lián)訂單集合 --> <collection property="orders" ofType="com.example.model.Order"> <id property="id" column="order_id"/> <result property="orderNo" column="order_no"/> <result property="amount" column="order_amount"/> <result property="userId" column="user_id"/> </collection> </resultMap> <select id="selectUserWithOrders" resultMap="UserWithOrdersMap"> SELECT u.id as user_id, u.name as user_name, u.age as user_age, o.id as order_id, o.order_no as order_no, o.amount as order_amount, o.user_id FROM user u LEFT JOIN orders o ON u.id = o.user_id WHERE u.id = #{userId} </select>
package com.example.model; import java.util.List; public class User { private Long id; private String name; private Integer age; private List<Order> orders; // 一對(duì)多關(guān)聯(lián)的訂單集合 // getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } }
package com.example.model; public class Order { private Long id; private String orderNo; private Double amount; private Long userId; // 外鍵,關(guān)聯(lián)用戶ID // getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public Double getAmount() { return amount; } public void setAmount(Double amount) { this.amount = amount; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } }
使用關(guān)聯(lián)查詢只需要指定以下兩個(gè)屬性即可
屬性名 | 是否必填 | 說明 |
---|---|---|
property | 必填 | Java對(duì)象中的集合屬性名稱 |
ofType | 條件必填 | 集合中元素的Java類型(當(dāng)不使用resultMap時(shí)必填) |
4.總結(jié)
①在 MyBatis 的 <resultMap>
中,如果使用 <association>
或 <collection>
映射關(guān)聯(lián)關(guān)系,必須為父對(duì)象(主對(duì)象)至少定義一個(gè) <id>
屬性
MyBatis 使用 <id>
來唯一標(biāo)識(shí)一個(gè)對(duì)象,用于:
- 一級(jí)/二級(jí)緩存的鍵值
- 解決嵌套映射中的循環(huán)引用問題
- 避免重復(fù)創(chuàng)建相同對(duì)象(性能優(yōu)化)
關(guān)聯(lián)映射的依賴:
- 當(dāng)存在
<association>
或<collection>
時(shí),MyBatis 需要通過父對(duì)象的<id>
來管理關(guān)聯(lián)對(duì)象的加載和綁定。
②association及collection中的id屬性是可選的,但建議加上,它用于避免重復(fù)子對(duì)象(例如 JOIN 導(dǎo)致重復(fù)數(shù)據(jù)時(shí)去重)。
如果子對(duì)象中定義了 <id>
屬性,MyBatis 會(huì)對(duì) <collection>
中的重復(fù)子對(duì)象進(jìn)行去重。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解如何使用ModelMapper庫進(jìn)行對(duì)象之間的屬性映射
這篇文章主要介紹了如何使用ModelMapper庫進(jìn)行對(duì)象之間的屬性映射實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07java中@EnableAutoConfiguration注解使用
在Spring Boot框架中,@EnableAutoConfiguration是一種非常重要的注解,本文就來介紹一下java中@EnableAutoConfiguration注解使用,感興趣的可以了解一下2023-11-11Java 策略模式與模板方法模式相關(guān)總結(jié)
這篇文章主要介紹了Java 策略模式與模板方法模式相關(guān)總結(jié),幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2021-01-01利用POI讀取word、Excel文件的最佳實(shí)踐教程
Apache POI 是用Java編寫的免費(fèi)開源的跨平臺(tái)的 Java API,Apache POI提供API給Java程式對(duì)Microsoft Office格式檔案讀和寫的功能。 下面這篇文章主要給大家介紹了關(guān)于利用POI讀取word、Excel文件的最佳實(shí)踐的相關(guān)資料,需要的朋友可以參考下。2017-11-11詳解如何使用MyBatis實(shí)現(xiàn)數(shù)據(jù)庫的CRUD
這篇文章主要為大家詳細(xì)介紹了如何使用MyBatis實(shí)現(xiàn)數(shù)據(jù)庫的CRUD操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-12-12SpringBoot快速搭建web項(xiàng)目詳細(xì)步驟總結(jié)
這篇文章主要介紹了SpringBoot快速搭建web項(xiàng)目詳細(xì)步驟總結(jié) ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12使用Idea或Datagrip導(dǎo)入excel數(shù)據(jù)的方法
這篇文章主要介紹了使用Idea或Datagrip導(dǎo)入excel數(shù)據(jù)的方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11SpringCloud將Nacos作為配置中心實(shí)現(xiàn)流程詳解
這篇文章主要介紹了Springcloud中的Nacos Config服務(wù)配置,本文以用戶微服務(wù)為例,進(jìn)行統(tǒng)一的配置,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10