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 属性来指定集合中元素的类型。

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

相关推荐
float_com几秒前
【java面向对象进阶】------抽象类+接口 综合实例
java
哈哈哈哈~23 分钟前
多线程之线程池
java·线程池
洛克大航海32 分钟前
7-SpringCloud-服务网关 Gateway-高级特性 Route
java·spring cloud·gateway·route
Dreams_l32 分钟前
redis中的数据类型
java·开发语言
梵得儿SHI33 分钟前
Java IO 流详解:字符流(Reader/Writer)与字符编码那些事
java·开发语言·字符编码·工作原理·字符流·处理文本
盖世英雄酱5813640 分钟前
java深度调试【第三章内存分析和堆内存设置】
java·后端
bug攻城狮1 小时前
SaaS多租户架构实践:字段隔离方案(共享数据库+共享Schema)
mysql·架构·mybatis·springboot·1024程序员节
007php0071 小时前
京东面试题解析:同步方法、线程池、Spring、Dubbo、消息队列、Redis等
开发语言·后端·百度·面试·职场和发展·架构·1024程序员节
小丁爱养花1 小时前
Redis 内部编码/单线程模型/string
数据库·redis·缓存·1024程序员节
爬山算法1 小时前
Redis(84)如何解决Redis的缓存击穿问题?
java·redis·缓存