1.引入
我们之前把查询的结果按照对象、对象集合进行了一个加载。但是呢,这一个过程是怎么实现的呢?如果说我们的查询结果和我们的封装对象之间无法进行连接。那么这一个时候又怎么处理?那么下面我们就一起来看看MyBatis的一个强大的功能:resultMap,实现高级结果集映射。
2.自定义结果映射规则
(1).编写查询接口以及相关查询方法
public interface EmployeeMapperPlus {
//按照id查询对应的实体对象
public Employee getEmpById(Integer id);
}
(2).在映射文件中编写对应的配置内容信息,这一个时候我们使用resultMap进行自定义封装
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp">
<!--指定主键列的封装规则:
id:定义主键会底层有优化;
column:指定哪一列
property:指定对应的javaBean属性
-->
<id column="id" property="id"/>
<!-- 定义普通列封装规则 -->
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<!-- 其他不指定的列会自动封装:但是建议我们只要写resultMap就把全部的映射规则都写上。
-->
</resultMap>
<!-- resultMap:自定义结果集映射规则; -->
<!-- public Employee getEmpById(Integer id); -->
<select id="getEmpById" resultMap="MySimpleEmp">
select * from tbl_employee where id=#{id}
</select>
(3).查询操作测试
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee empById = mapper.getEmpById(1);
System.out.println(empById);
总结:使用resultMap进行自定义封装
1.我们之前一直使用的是resultType,现在使用resultMap。在映射文件中定义的时候只能够选择使用一个。
2.使用resultMap自定义封装,也就是通过指定一个新的规则来指定如何把数据库列名称和实体对象中的属性进行一个一一对应, 然后把结果加载到实体对象中去。
3.注意自定义resultMap的定义规则,以及相关属性的指定,以及各个属性的含义是什么。
3.resultMap进行关联查询(一对一情况,使用resultMap以及association)
(1).定义俩个关联的实体对象
//实体对象:员工
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
}
//实体对象:部门
public class Department {
private Integer id;
private String departmentName;
}
(2).编写查询接口以及相关查询方法
//定义相关的查询方法
public interface EmployeeMapperPlus {
public Employee getEmpAndDept(Integer id);
}
(3).在映射文件中编写对应的配置内容信息
①:使用resultMap进行级联属性封装结果集
<!--
联合查询:级联属性封装结果集
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>
<!-- public Employee getEmpAndDept(Integer id);-->
<select id="getEmpAndDept" resultMap="MyDifEmp">
SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
WHERE e.d_id=d.id AND e.id=#{id}
</select>
②:使用association定义
<!--
使用association定义关联的单个对象的封装规则;
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<!-- association可以指定联合的javaBean对象
property="dept":指定哪个属性是联合的对象
javaType:指定这个属性对象的类型[不能省略]
-->
<association property="dept" javaType="com.atguigu.mybatis.bean.Department">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
(4).查询操作测试
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee empAndDept = mapper.getEmpAndDept(1);
System.out.println(empAndDept);
System.out.println(empAndDept.getDept());
4.resultMap进行关联查询(association分步查询)
需求:我们需要通过分步查询的方式进行对数据的查询操作,先查询出员工对象的信息,然后再在员工对象中的部门编号去查询部门的相关信息。
(1).编写查询接口以及相关查询方法
//分步查询,按照员工编号进行员工信息查询
public interface EmployeeMapperPlus {
public Employee getEmpByIdStep(Integer id);
}
//分步查询,按照部门编号进行部门信息查询
public interface DepartmentMapper {
public Department getDeptById(Integer id);
}
(2).在映射文件中编写对应的配置内容信息
①:定义按照部门编号查询部门信息
<mapper namespace="com.atguigu.mybatis.dao.DepartmentMapper">
<!--public Department getDeptById(Integer id); -->
<select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department">
select id,dept_name departmentName from tbl_dept where id=#{id}
</select>
</mapper>
②:定义按照员工编号查询员工信息
<!-- 使用association进行分步查询:
1、先按照员工id查询员工信息
2、根据查询员工信息中的d_id值去部门表查出部门信息
3、部门设置到员工中;
-->
<!-- id last_name email gender d_id -->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<!-- association定义关联对象的封装规则
select:表明当前属性是调用select指定的方法查出的结果
column:指定将哪一列的值传给这个方法
流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
-->
<association property="dept"
select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id">
</association>
</resultMap>
<!-- public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
select * from tbl_employee where id=#{id}
<if test="_parameter!=null">
and 1=1
</if>
</select>
(3).查询操作测试
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee employee = mapper.getEmpByIdStep(3);
System.out.println(employee);
System.out.println(employee.getDept())
总结:
1.使用级联查询的时候,需要注意使用association进行对不同的映射文件之间的调用的定义方法。
5.resultMap进行关联查询(association分步查询&延时加载)
(1).延迟加载的意义:
我们在实体对象的定义的时候把俩个实体之间进行了一个关联。那么当我们进行查询的时候是把俩个实体对象的信息都一并查询了出来。但是有的时候我们仅仅只需要其中的一个。那么这一个时候我们就可以使用延时加载。
使用了延时加载以后,我们就能够有效的节省数据库操作的相关资源。
(2).如何实现:
①:先配置好分段查询(即:需要定义好关联的查询)
②:在全局配置文件(mybatis-config.xml)中进行配置
<settings>
<!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
(4).代码配置和测试同4操作