目录
1.reusltmap的说明
resultmap定义了数据库的结果映射到java对象的规则,resultmap包含4个属性:
-
id
: ResultMap 的唯一标识 -
type
: 映射到的 Java 类型(全限定类名或别名) -
extends
: 继承另一个 ResultMap -
autoMapping
: 是否开启自动映射(true/false)
前三个比较常用
resultmap包含以下子元素,并且子元素是有定义顺序的,如下:
-
<constructor>
(可选) -
<id>
(至少一个) -
<result>
(零个或多个) -
<association>
(零个或多个) -
<collection>
(零个或多个) -
<discriminator>
(可选)
-
必须遵循上述顺序,如果顺序不正确,MyBatis 在解析 XML 时会抛出异常
-
<id>
元素必须出现在<result>
元素之前 -
如果使用
<constructor>
,它必须是第一个元素 -
<discriminator>
必须是最后一个元素(如果存在)
2.association的使用
<association>
是 MyBatis 中用于处理一对一关联关系的元素,它可以将查询结果中的一部分数据映射到一个复杂的关联对象中。
在实际开发中,如果想一次查询两张表的数据,不想通过两次查询的方式,而是想一次查询出来,可以通过两张表关联将表A和表B的数据都查询出来
属性名 | 说明 |
---|---|
property |
Java对象中的属性名 |
javaType |
关联对象的Java类型(全限定类名或别名) |
resultMap |
引用外部定义的resultMap |
column |
传递给嵌套查询的列名(可以是多个列:column="{prop1=col1,prop2=col2}" ) |
select |
另一个映射语句的ID,用于嵌套查询 |
fetchType |
覆盖全局的延迟加载设置(lazy/eager) |
autoMapping |
是否启用自动映射(true/false) |
<!-- 一对一关联映射示例 -->
<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"/>
<!-- 一对一关联 department 对象 -->
<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; // 对应 user_id 字段
private String name; // 对应 user_name 字段
private Integer age; // 对应 user_age 字段
private Department department; // 一对一关联对象
// 必须的 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; // 对应 dept_id 字段
private String deptName; // 对应 dept_name 字段
private String location; // 对应 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;
}
}
使用关联查询只需要指定以下两个属性即可
|-------------------------|-----------------------------------|
| 配置项 | 作用 |
| property="department"
| 指定 User 类中关联属性的名称(需与字段名一致)。 |
| javaType
| 指定关联对象的完整类名(可省略,MyBatis 通常能自动推断)。 |
3.collection的使用
<collection>
是 MyBatis 中用于处理一对多关联关系的核心元素,它能够将查询结果中的多条记录映射到一个集合属性中(如 List、Set 等)
属性名 | 是否必填 | 说明 |
---|---|---|
property |
必填 | Java对象中的集合属性名称 |
ofType |
条件必填 | 集合中元素的Java类型(当不使用resultMap 时必填) |
column |
条件必填 | 传递给嵌套查询的列名(使用select 时必填) |
select |
可选 | 另一个映射语句的ID,用于嵌套查询 |
fetchType |
可选 | 加载方式(lazy/eager),覆盖全局配置 |
javaType |
可选 | 集合的Java类型(如ArrayList、HashSet等) |
resultMap |
可选 | 引用外部定义的resultMap |
autoMapping |
可选 | 是否启用自动映射(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"/>
<!-- 一对多关联订单集合 -->
<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; // 一对多关联的订单集合
// 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; // 外键,关联用户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;
}
}
使用关联查询只需要指定以下两个属性即可
| 属性名 | 是否必填 | 说明 |
| property
| 必填 | Java对象中的集合属性名称 |
ofType |
条件必填 | 集合中元素的Java类型(当不使用resultMap 时必填) |
---|
4.总结
①在 MyBatis 的 <resultMap>
中,如果使用 <association>
或 <collection>
映射关联关系,必须为父对象(主对象)至少定义一个 <id>
属性
-
MyBatis 使用
<id>
来唯一标识一个对象,用于:-
一级/二级缓存的键值
-
解决嵌套映射中的循环引用问题
-
避免重复创建相同对象(性能优化)
-
-
关联映射的依赖 :
当存在
<association>
或<collection>
时,MyBatis 需要通过父对象的<id>
来管理关联对象的加载和绑定。
②association及collection中的id属性是可选的,但建议加上,它用于避免重复子对象(例如 JOIN 导致重复数据时去重)。如果子对象中定义了 **<id>**属性,MyBatis 会对 **<collection>**中的重复子对象进行去重。