Mybatis上手教程–select语句的resultMap配合association使用案例
一 association标签的使用场景
- 对于多表关联查询时,查询员工时连带其所在部门信息一起查询的场景。除了类似前面通过resultMap的级联属性配置的场景之外,还可以使用association标签来实现。
- 另外,对于分步查询的场景也可以使用association标签。
二association标签实现多表联合查询
在SQL mapper文件里重新写一个resultMap标签:
<resultMap id="myEmpDeptAssociation" type="com.knockatdatabase.Employee">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="email" property="mail"></result>
<association property="department" javaType="com.knockatdatabase.Department">
<id column="did" property="id"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
关于association标签的解释:首先,我们可以从字面意思上可以理解association本身就表示关联、联盟的意思。
- property=“department”表示的是,要对员工信息表对应的实体类Employee里的成员变量department进行关联,即员工信息表对应的实体类Employee里的成员属性名叫什么,这里就写什么;
- javaType=”com.knockatdatabase.Department”表示的是,Employee实体类的department属性,指向我这个实体类;
这样一来,就相当于是Employee实体类里的属性department指定了对应的数据类型。跟前面我们使用级联设置属性达到了相同的目的和作用。
然后,在SQL mapper文件里写的SQL,就是这样的:
<select id="getEmployeeAndDepartmentById" resultMap="myEmpDeptAssociation">
select emp.id,emp.gender,emp.email as email,emp.last_name,emp.did did,dept.dept_name
from tbl_employee emp,tbl_dept dept
where emp.did=dept.id and emp.id=#{id}
</select>
即,resultMap指向了这个新配置的带有association标签的myEmpDeptAssociation。然后,Java测试类里执行的结果依然是正确的。
三 association实现分步查询的场景
我们想要实现查询员工信息的同时,顺带查询部门信息,除了上述的多表关联查询,也可以使用分步查询。即先通过查询员工信息表,传入员工id作为参数,这样可以获取员工所在的部门id,然后用这个部门id当作参数,去查询部门信息表,这样就获得了部门信息,最后把员工信息和部门信息拼接在一起。就相当于通过分步的方式,获取员工信息的同时也获取了部门信息。完整流程如下:
1 先创建和实体类Department对应的接口,DepartmentMapper.java
package com.knockatdatabase.dao;
import com.knockatdatabase.Department;
/**
* @Author:asher
* @Date:2021/10/11 17:15
* @Description:com.knockatdatabase.dao
* @Version:1.0
*/
public interface DepartmentMapper {
Department getDepartmentById(Integer id);
}
2 新建并配置对应的SQL mapper文件,DepartmentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.knockatdatabase.dao.DepartmentMapper">
<select id="getDepartmentById" resultType="com.knockatdatabase.Department">
select id,dept_name as deptName from tbl_dept where id=#{id}
</select>
</mapper>
3 Mybatis配置文件里添加关于DepartmentMapper.xml文件的配置
<mappers>
<mapper resource="Employee.xml"/>
<mapper resource="EmployeeMapper.xml"/>
<mapper resource="DepartmentMapper.xml"></mapper>
</mappers>
前面3个步骤,相当于是做的准备工作。即,通过部门id获取部门信息的SQL,给后续的分步查询员工信息做准备。
4 EmployeeMapper.java定义新的方法
Employee getEmployeeAndDepartmentByIdStep(Integer id);
注意,这里是1个新的方法。
5 SQL mapper文件EmployeeMapper.xml添加resultMap和association以及SQL
<!-- 分步查询的思路
1 先根据员工id查询员工信息,并获取部门id;
2 根据查询的部门id当作参数,去查询并获取部门信息;
3 把查询到的部门信息,设置到查询出来的员工信息里去。
-->
<resultMap id="getEmpAndDeptByStep" type="com.knockatdatabase.Employee">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="email" property="mail"></result>
<result column="gender" property="gender"></result>
<!-- association标签来定义关联对象department的属性-->
<!-- 表示的是关联的对象department通过select指定的包.方法来获取
然后,column=“did“,表示的是,我前面的查询里获取到的结果,作为参数,传递给这个方法-->
<association property="department" select="com.knockatdatabase.dao.DepartmentMapper.getDepartmentById" column="did">
</association>
</resultMap>
<select id="getEmployeeAndDepartmentByIdStep" resultMap="getEmpAndDeptByStep">
select * from tbl_employee where id=#{id}
</select>
注意:这里的核心思路:
- 先新建1个resultMap,resultMap id=”getEmpAndDeptByStep” type=”com.knockatdatabase.Employee”,用于处理查询员工表及其关联department表的信息的;此处的id标签和result标签跟以前的方式一样配置;
- 通过<association property=”department” select=”com.knockatdatabase.dao.DepartmentMapper.getDepartmentById” column=”did”>配置,就比较有意思了,指定员工信息表对应的Javabean的属性字段department,是通过select属性指定的对应的接口.方法来获取的,其中,column字段表示的是用哪个查询出来的字段当作参数,传递给该方法,并从该方法中去获取对应的部门信息;
- 最后把获取到的部门信息拼接到员工信息上去,这样就形成了一个完整的员工信息;
6 Java测试代码
@Test
public void testGetEmployeeAndDepartmentByIdStep() {
String resource = "mybatis-config.xml";
SqlSession sqlSession = null;
try{
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employeeAndDepartmentById = mapper.getEmployeeAndDepartmentByIdStep(1);
System.out.println("employee info: " + employeeAndDepartmentById);
Department department = employeeAndDepartmentById.getDepartment();
System.out.println("department info:" + department);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
//结果
employee info: Employee{id=1, lastName='黄伟', gender='男', mail='huangwei@knockatdatabase.com', department=Department{id=1, deptName='市场部'}}
department info:Department{id=1, deptName='市场部'}
四小结
利用resultMap结合association标签一起使用,可以构成比较复杂一点儿的查询。当然,这种场景在实际工作场景中是否真的实用,我暂时还不是特别清楚。至少,我觉得这个分步查询,只是一个功能性的东西而已,可能并不实用。远不及一条关联查询来的更方便直接高效又简洁。
一条评论
Pingback: