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

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

相关推荐
月光水岸New1 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6751 小时前
数据库基础1
数据库
我爱松子鱼1 小时前
mysql之规则优化器RBO
数据库·mysql
闲猫1 小时前
go orm GORM
开发语言·后端·golang
427724001 小时前
IDEA使用git不提示账号密码登录,而是输入token问题解决
java·git·intellij-idea
丁卯4042 小时前
Go语言中使用viper绑定结构体和yaml文件信息时,标签的使用
服务器·后端·golang
chengooooooo2 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
李长渊哦2 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
计算机小白一个2 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
Rverdoser3 小时前
【SQL】多表查询案例
数据库·sql