数据表中经常存在的多对一以及一对多的情况,例如多个员工属于一个部门(多对一), 一个部门有多个员工(一对多)。在Mybatis中普通的查询返回值为实体类对象不能实现以上操作。这就有了xml文件中 自定义映射resultMap的应用。
一、 resultMap处理字段和属性的映射关系
- resultMap:设置自定义映射
- 属性:
- id:表示自定义映射的唯一标识,不能重复
- type:查询的数据要映射的实体类的类型
- 子标签:
- id:设置主键的映射关系
- result:设置普通字段的映射关系
- 子标签属性:
- property:设置映射关系中实体类中的属性名
- column:设置映射关系中表中的字段名
应用:
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"></id>
<!-- 实现属性名和数据库中字段名的映射-->
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<!--查询所有用户信息-->
<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>
二、多对一查询
三种方法可以实现多对一查询:
- 级联属性赋值
- 使用association处理映射关系
- 分步查询
员工信息:
public class Emp {
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
//...构造器、get、set方法等
}
部门类:
public class Dept {
private Integer did;
private String deptName;
private List<Emp> emps;
//...构造器、get、set方法等
2.1 级联属性赋值
通过左连接将两个表进行连接,并通过resultMap属性为两个表赋值,其中员工表中的部门信息采用 类.属性名作为 property值。
/**
* 查询员工信息以及其所在的部门信息
*/
Emp selectEmpAndDept(@Param("eid") Integer eid);
<resultMap id="EmpAndDept" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp selectEmpAndDept(@Param("eid") String eid);-->
<select id="selectEmpAndDept" resultMap="EmpAndDept">
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>
2.2 使用association处理映射关系
<!--
处理多对一映射关系方式二: 使用association处理映射关系
association:处理多对一的映射关系
property: 需要处理多对的映射关系的属性名
javaType:该属性的类型 (通过反射实现)
再进行属性注入
-->
<resultMap id="EmpAndDeptTwo" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<!--Emp selectEmpAndDept(@Param("eid") String eid);-->
<select id="selectEmpAndDept" resultMap="EmpAndDeptTwo">
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>
2.3 分步查询
分步查询无可厚非就是将查询分为两步,一 先通过eid查询员工的所有信息,二 通过员工信息中的did属性再去部门表中查询部门的所有信息,然后再进行输出。
/**
* 通过分布查询查询员工信息及其所在的部门
* 一:查询员工信息
* empMapper中实现
*/
Emp getEmpAndDeptByStepOne(@Param("eid")Integer eid);
/**
* 二:根据did查询员工所对应的部门
* deptMapper中实现
*/
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
EmpMapper 的xml文件,实现第一步查询
<!--
select: 设置分步查询的sql的唯一标识 mapper接口的全类名.方法名
column: 设置分布查询的条件
fetchType: 设置fetchType为true时,执行立即加载,延迟加载不再其作用,手动控制延迟加载的效果 lazy表示延迟加载
-->
<resultMap id="empAndDeptByStepOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept"
select="com.java.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"
fetchType="eager"></association>
</resultMap>
<!-- Emp getEmpAndDeptByStepOne(@Param("eid")Integer id);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepOne">
select * from t_emp where eid = #{eid}
</select>
DeptMapper.xml实现第二步查询
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
select * from t_dept where did = #{did}
</select>
三、一对多查询
两种方法可以实现多对一查询:
- collection集合属性 (ofType)
- 分步查询
3.1 collection集合属性实现
/**
* 获取部门以及部门中员工信息
*/
Dept getDeptAndEmp(@Param("did") Integer did);
<!--
collection: 用来处理一对多的映射关系
property :表示一对多中 ”多“在类中的属性名
ofType:表示该属性所对应的集合中所存储数据的类型
-->
<resultMap id="deptAndEmp" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="deptAndEmp">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>
3.2 分步查询
/**
* 通过分布查询查询部门以及部门中所有的员工信息
* 分布查询第一步: 查询部门信息
*/
Dept getDeptAndEmpOne(@Param("did")Integer did);
/**
* 通过分布查询查询部门以及部门中所有的员工信息
* 分布查询第二步: 根据did查询员工信息
*/
List<Emp> getDeptAndEmpTwo(@Param("did")Integer did);
<resultMap id="DeptAndEmpByStepOne" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps"
select="com.java.mybatis.mapper.EmpMapper.getDeptAndEmpTwo"
column="did"></collection>
</resultMap>
<!-- Dept getDeptAndEmpOne(@Param("did")Integer did);-->
<select id="getDeptAndEmpOne" resultMap="DeptAndEmpByStepOne">
select * from t_dept where did = #{did}
</select>
<!-- List<Emp> getDeptAndEmpTwo(@Param("did")Integer did);-->
<select id="getDeptAndEmpTwo" resultType="emp">
select * from t_emp where did = #{did}
</select>