多表联查
员工-部门 一对多:员工中有一个属性存储部门对象
部门-员工 多对一:部门中有一个属性存储员工对象集合
一次查询,通过员工 id 查询员工信息以及所在部门信息
方法一:resultMap 逐个配置 字段与属性对象的属性之间的映射关系
接口类声明方法
Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);
配置 resultMap 设置字段与属性的映射关系
<resultMap id="empAndDeptResultMap" type="Emp">
<!-- id 主键和属性映射关系-->
<id column="emp_id" property="empId"></id>
<!-- result 普通字段和属性映射关系-->
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!-- 属性为对象时,property = "对象.属性" -->
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
SQL语句 左连接实现多表联查
<!-- Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
SELECT t_emp.*, t_dept.dept_name
FROM t_emp
LEFT JOIN t_dept
ON t_emp.dept_id = t_dept.dept_id
WHERE t_emp.emp_id = #{empId}
</select>
测试方法
@Test
public void testGetEmpAndDeptByEmpId(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByEmpId(2);
System.out.println(emp);
}
结果
Emp{empId=2, empName='李四', age=22, gender='男', dept=Dept{deptId=1, deptName='A'}}
方法二:resultMap 中使用 association 标签,专门处理实体类属性的多对一关系
association 和 collection 都是专门用于处理实体类型的属性的标签
配置 resultMap 中 association 标签,属性 映射到实体类,从而字段映射到实体类的属性
<resultMap id="empAndDeptResultMap" type="Emp">
<!-- id 主键和属性映射关系-->
<id column="emp_id" property="empId"></id>
<!-- result 普通字段和属性映射关系-->
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
其他步骤同方法一
方法三:分步查询,适用于 >=2张表的联查,先查员工信息,获得 dept_id 再查部门信息
查询步骤一:员工 emp_id 查询员工信息,将信息中的部门 dept_id 作为参数传给第二步查询
接口类声明方法一
Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);
配置 resultMap 设置字段与属性的映射关系,以及调用第二步查询
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<!-- id 主键和属性映射关系-->
<id column="emp_id" property="empId"></id>
<!-- result 普通字段和属性映射关系-->
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
property 设置需要处理映射关系的属性的属性名
select 定位分步查询的下一步查询,唯一标识= "namespace.id"
column 将下一步查询需要的字段作为参数传入查询方法中
select+column 就是调用方法+传参的过程
-->
<association property="dept"
select="com.zzz.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id"></association>
</resultMap>
SQL语句和单表查询员工信息相同
<!-- Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
SELECT * FROM t_emp WHERE emp_id = #{empId}
</select>
查询步骤二:根据步骤一传入的参数 dept_id 查询部门信息,简单的单表查询
接口类声明方法二
Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);
部门的属性中没有实体类型的属性,不需要 resultMap (需要在mybatis核心配置文件中开启下划线自动转驼峰)
<!-- Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);-->
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
SELECT * FROM t_dept WHERE dept_id = #{deptId}
</select>
测试
@Test
public void testGetEmpAndDeptByEmpId(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp);
}
结果
Emp{empId=1, empName='张三', age=20, gender='男', dept=Dept{deptId=1, deptName='A'}}
各个要素之间的对应关系
分步查询的优势 - 可以实现延迟加载
但是必须在核心配置文件中设置全局配置信息:
<!-- Mybatis全局配置 -->
<settings>
<!-- 开启延迟加载功能 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置按需加载 -->
<setting name="aggressiveLazyLoading" value="flase"/>
</settings>
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加载)|eager(立即加载)"
实现按需使用分步查询,如果没有获取第二步的信息,则只会执行第一步
测试,只获取员工信息
@Test
public void testGetEmpAndDeptByEmpId(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName());
}
结果
DEBUG 02-13 17:10:28,875 ==> Preparing: SELECT * FROM t_emp WHERE emp_id = ? (BaseJdbcLogger.java:137)
DEBUG 02-13 17:10:28,910 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-13 17:10:28,982 <== Total: 1 (BaseJdbcLogger.java:137)
张三
从结果中可以看出,只执行了分步查询的第一步: SELECT * FROM t_emp WHERE emp_id = ?
关闭懒加载:执行所有步骤
DEBUG 02-13 17:11:42,451 ==> Preparing: SELECT * FROM t_emp WHERE emp_id = ? (BaseJdbcLogger.java:137)
DEBUG 02-13 17:11:42,483 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-13 17:11:42,515 ====> Preparing: SELECT * FROM t_dept WHERE dept_id = ? (BaseJdbcLogger.java:137)
DEBUG 02-13 17:11:42,516 ====> Parameters: 1(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-13 17:11:42,519 <==== Total: 1 (BaseJdbcLogger.java:137)
DEBUG 02-13 17:11:42,519 <== Total: 1 (BaseJdbcLogger.java:137)
张三
在开启了延迟加载后,可以在 association 标签中为单个 resultMap设置为立即加载
fetchType="eager|lazy" eager-立即加载, lazy-延迟加载(默认)
<association property="dept"
fetchType="eager"
select="com.zzz.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id"></association>
标签:Mybatis10,查询,dept,emp,属性,id,加载
From: https://www.cnblogs.com/Ashen-/p/17117825.html