MyBatis 自定义映射 ResultMap:一对多映射关系处理

在 MyBatis 中处理一对多 (或称为一对集合)的映射关系时,我们通常会使用 collection 标签或分布查询来定义这种关系。这种关系常见于一个部门有多个员工这样的场景。下面我们将详细探讨如何使用 MyBatis 的 resultMap 来处理这种一对多的关系。

实体类定义

首先,我们有两个实体类:Dept(部门)和 Emp(员工)。其中 Dept 类包含一个 List<Emp> 类型的 emps 属性,表示该部门下的所有员工。

java 复制代码
public class Dept {  

    private Integer did;  
    private String deptName;  
    private List<Emp> emps;  
      
    // 省略构造器、getter 和 setter 方法  
}  
java 复制代码
public class Emp {  

    private Integer eid;  
    private String empName;  
    private Integer age;  
    private String sex;  
    private String email;  
      
    // 省略构造器、getter 和 setter 方法  
}

使用 collection 标签

在 MyBatis 的映射文件中,我们使用 collection 标签来处理一对多的映射关系。ofType 属性指定了集合中元素的类型。

xml 复制代码
<resultMap id="DeptAndEmpResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"/>
	
	<collection property="emps" ofType="Emp">
		<id property="eid" column="eid"/>
		<result property="empName" column="emp_name"/>
		<result property="age" column="age"/>
		<result property="sex" column="sex"/>
		<result property="email" column="email"/>
	</collection>
</resultMap>

<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
	select * from t_dept 
	left join t_emp on t_dept.did = t_emp.did 
	where t_dept.did = #{did}
</select>

分步查询处理一对多映射

分步查询是一种更加灵活的方式,它允许我们先查询主对象(如部门),然后再根据主对象的信息去查询与之关联的子对象(如员工)。在 MyBatis 中,我们可以使用 collection 标签的 select 属性来指定子查询的 SQL 映射 ID。

  1. 首先查询部门信息
java 复制代码
/**
 * 通过分步查询,查询部门及对应的所有员工信息
 * 分步查询第一步:查询部门信息
 * @param did 
 * @return com.example.mybatis.pojo.Dept
 */
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
xml 复制代码
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"></result>
	<collection property="emps"
				select="com.exapmle.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
				column="did"></collection>
</resultMap>

<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
	select * from t_dept where did = #{did}
</select>
  1. 再根据部门 id 查询部门中的所有员工
java 复制代码
/**
 * 通过分步查询,查询部门及对应的所有员工信息
 * 分步查询第二步:根据部门id查询部门中的所有员工
 * @param did
 * @return java.util.List<com.exapmle.mybatis.pojo.Emp>
 */
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
xml 复制代码
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
	select * from t_emp where did = #{did}
</select>

在分步查询中,主查询(getDeptAndEmpByStepOne)首先执行,然后对于主查询结果中的每个部门,都会执行一次子查询(getDeptAndEmpByStepTwo)来获取该部门下的所有员工。这种方式的好处是它可以减少一次性从数据库中加载的数据量 ,提高性能。但是,它也会增加数据库访问的次数。因此,在选择是否使用分步查询时,需要根据实际情况进行权衡。

总结

MyBatis 的 resultMap 提供了强大的自定义映射功能,可以灵活地处理各种复杂的数据关系。在处理一对多映射关系时,我们可以使用 collection 标签来定义这种关系,并通过设置 ofType 属性来指定集合中元素的类型。

此外,我们还可以使用分步查询的方式来优化性能。无论选择哪种方式,都需要根据实际需求进行权衡和选择。

相关推荐
Yvemil728 分钟前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。30 分钟前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
一个程序员_zhangzhen39 分钟前
sqlserver新建用户并分配对视图的只读权限
数据库·sqlserver
zfj32142 分钟前
学技术学英文:代码中的锁:悲观锁和乐观锁
数据库·乐观锁··悲观锁·竞态条件
吴冰_hogan44 分钟前
MySQL InnoDB 存储引擎 Redo Log(重做日志)详解
数据库·oracle
.生产的驴1 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
爱上语文1 小时前
宠物管理系统:Dao层
java·开发语言·宠物
顽疲1 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端
nbsaas-boot1 小时前
探索 JSON 数据在关系型数据库中的应用:MySQL 与 SQL Server 的对比
数据库·mysql·json
机器之心1 小时前
AAAI 2025|时间序列演进也是种扩散过程?基于移动自回归的时序扩散预测模型
人工智能·后端