在 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。
- 首先查询部门信息
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>
- 再根据部门 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
属性来指定集合中元素的类型。
此外,我们还可以使用分步查询的方式来优化性能。无论选择哪种方式,都需要根据实际需求进行权衡和选择。