一对多映射处理
一对多的关系,例如一个部门有多名员工,一个班级有多名学生
解决方案是:在一的方
添加集合并且指定集合的泛型是多方类型
【就是JavaBean
类型】
// 在一的方添加集合,泛型指定为多的一方类型,并且提供getter和setter方法
private List<Emp> emps;
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
方式一:collection
方式
collection
标签的说明:
ofType
是为集合指定类型
property
是为哪个属性赋值
例如
<!--
ofType:设置collection标签所处理的集合属性中存储数据的类型
-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="ename" column="ename"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
</collection>
案例:
Mapper
接口
/**
*根据部门ID查询该部门中所有员工
*/
Dept getDeptAndEmpByID(@Param("did")Integer did);
Mapper.xml
文件
<resultMap id="DeptAndEmpResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dept_name"/>
<!--
collection:表示为集合赋值,property表示为Dept类中的emps赋值
ofType:表示集合的类型是Emp
-->
<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>
<!--
根据部门ID查询对应的部门所有员工
getDeptAndEmpByID(@Param("did")Integer did);
-->
<select id="getDeptAndEmpByID" resultMap="DeptAndEmpResultMap">
select d.did,d.dept_name,e.eid,e.emp_name,e.age,e.sex,e.email
from dept as d inner join emp as e on d.did=e.did where d.did = #{did};
</select>
test
类
// 一对多使用collection解决
@Test
public void testGetDeptAndEmpByID(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.getDeptAndEmpByID(1);
System.out.println(dept);
List<Emp> emps = dept.getEmps();
emps.forEach(emp -> System.out.println(emp));
}
方式二:分步查询【重点】
分步查询就是将一条sql
语句,分成多步查询获取最终结果
同样需要使用association
标签,标签需要这两个属性select
和column
标签属性说明:
select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
column:设置分布查询的条件
fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
案例:查询指定部门信息及该部门的所有员工
步骤的解释:
- 先是第一步查询到的
did
【部门id
】给第二步查询的条件赋值,使用的属性是column
- 第二步查询到的结果给
Emp
对象赋值 - 第三步是将第二的查询到的
Dept
对象值赋值给指定的属性 如:<association property="emps"
注意是:select
是指第二条sql
的位置【位置是mapper接口的全类名.方法名
】
案例:查询指定部门信息及该部门的所有员工
Mapper
接口
第一步:
/**
* 分步查询第一步;
* 根据部门ID查询部门信息及该部门所有员工
* 先查询出该部门的ID
* 再根据该部门ID查询该的所有员工
*/
Dept getDeptAndEmpByStepOnt(@Param("did")Integer did);
第二步:
/**
* 分步查询第二步:
* 根据部门ID查询该部门对应所有员工
*/
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
Mapper.xml
文件
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dept_Name"/>
<!--
select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
column:设置分布查询的条件
fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
fetchType="lazy|eager":lazy表示延迟加载【也是默认值,一般设置该值】,eager表示立即加载
-->
<collection property="emps"
select="com.haikang.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"
fetchType="lazy"/>
</resultMap>
<!--
getDeptAndEmpByStepOnt(@Param("did")Integer did);
分步查询:第一步先查询出该部门的ID
第二步再根据该部门ID查询该部门的所有员工
-->
<select id="getDeptAndEmpByStepOnt" resultMap="DeptAndEmpByStepOneResultMap">
select * from dept where did = #{did};
</select>
test
类
// 一对多使用分步查询
@Test
public void testGetDeptAndEmpByStep(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.getDeptAndEmpByStepOnt(1);
System.out.println(dept);
List<Emp> emps = dept.getEmps();
emps.forEach(emp -> System.out.println(emp));
}
总结
如果查询只是单表时,字段名与属性名不一致,使用别名
解决
如果查询是多表时,使用分步查询,实现查询之间的独立性【同时也是分步查询的好处】