Mybatis结果集映射方式有两种,分别为 自动映射 和 自定义映射
自动映射【resultType】
自定义映射【resultMap】
一.自动映射与自定义映射
- 自动映射【resultType】:指的是自动将表中的字段与类中的属性进行关联映射
- 自动映射解决不了两类问题
- 多表连接查询时,需要返回多张表的结果集
- 单表查询时,不支持驼峰式自动映射【不想为字段定义别名】
- 自动映射解决不了两类问题
- 自定义映射【resultMap】:自动映射解决不了问题,交给自定义映射
- 注意:resultType与resultMap只能同时使用一个
二.自定义映射-级联映射
Dept类
@Data
public class Dept{
//部门id和名字
private Integer deptId;
private String deptName;
}
Employee类
@Data
public class Employee{
private Integer id; //员工id
private String lastName; //员工姓名
private String email; //员工邮箱
private Double salary; //员工薪资
private Dept dept; //员工所属部门信息的对象属性
mybatis-config.xml
<!-- 自定义映射【员工与部门关系】-->
<!--type 主要查询的数据还是 员工的,所以用 employee-->
<resultMap id="empAndDeptResyltMap" type="employee">
<!-- 定义主键字段与属性关联关系-->
<!-- column 是字段,对应的是数据库的列名, property 是属性,对应的是 类的属性名-->
<id column="id" property="id"></id>
<!-- 定义非主键字段与属性关联关系-->
<result column="last_name" property="lastName"></result>
<result column="email" property="email"></result>
<result column="salary" property="salary"></result>
<!-- 为员工所属部门,自定义关联关系-->
<!-- 级联映射 员工中的部门对象 dept,对象中的id属性 deptId,所以就有了 dept.deptId -->
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
<select id="selectEmpAndDeptByEmpId" resultMap="empAndDeptResyltMap">
# 这个 resultMap 和 上面自定义映射的 resultMap 值一样
SELECT
e.`id`,
e.`email`,
e.`last_name`,
e.`salary`,
d.`dept_id`,
d.`dept_name`
FROM
# 表名 ,e d 分别是 表的别名
tbl_employee e,
tbl_dept d
WHERE
# 多表查询的条件
e.`dept_id` = d.`dept_id`
AND
e.`id` = #{empId}
</select>
三.自定义映射-association映射
- association 可以解决一对一映射关系【一对多】
- 实例代码:
<!-- 自定义映射【员工与部门关系】-->
<!--type 主要查询的数据还是 员工的,所以用 employee-->
<resultMap id="empAndDeptResyltMapAssociation" type="employee">
<!-- 定义主键字段与属性关联关系-->
<!-- column 是字段,对应的是数据库的列名, property 是属性,对应的是 类的属性名-->
<id column="id" property="id"></id>
<!-- 定义非主键字段与属性关联关系-->
<result column="last_name" property="lastName"></result>
<result column="email" property="email"></result>
<result column="salary" property="salary"></result>
<!-- 为员工所属部门,自定义关联关系-->
<!-- association -->
<association property="dept" javaType="属性的类型">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
<select id="selectEmpAndDeptByEmpIdAssociation" resultMap="empAndDeptResyltMapAssociation">
# 这个 resultMap 和 上面自定义映射的 resultMap 值一样
SELECT
e.`id`,
e.`email`,
e.`last_name`,
e.`salary`,
d.`dept_id`,
d.`dept_name`
FROM
# 表名 ,e d 分别是 表的别名
tbl_employee e,
tbl_dept d
WHERE
# 多表查询的条件
e.`dept_id` = d.`dept_id`
AND
e.`id` = #{empId}
</select>
表连接查询会影响性能,如何不使用表连接查询还能进行多表查询?
- 通过员工id获取员工信息及员工所属的部门信息【分步查询】
- 先通过员工id获取员工信息【id,last_name,email,salary,dept_id】
- 再通过部门id获取部门信息【dept_id,dept_name】
四.自定义映射-collection映射
Dept类
@Data
public class Dept{
//部门id和名字
private Integer deptId;
private String deptName;
//一对多【dept -> emp】
private List<Employee> empList;
}
定义一对多的关联关系
<!-- 自定义映射【员工与部门关系】-->
<!--type 主要查询的数据还是 部门的,所以用 dept-->
<resultMap id="deptAndempResultMap" type="dept">
<!-- 定义主键字段与属性关联关系-->
<!-- column 是字段,对应的是数据库的列名, property 是属性,对应的是 类的属性名-->
<id column="dept_id" property="deptId"></id>
<!-- 定义非主键字段与属性关联关系-->
<result column="dept_name" property="deptName"></result>
<!-- 为员工所属部门,自定义关联关系-->
<collection property="empList"
ofType="属性的类型">
<id column="id" property="id"></id>
<!-- 定义非主键字段与属性关联关系-->
<result column="last_name" property="lastName"></result>
<result column="email" property="email"></result>
<result column="salary" property="salary"></result>
</collection>
</resultMap>
<select id="selectDeptAndEmpByDeptId" resultMap="deptAndempResultMap">
# 这个 resultMap 和 上面自定义映射的 resultMap 值一样
SELECT
e.`id`,
e.`email`,
e.`last_name`,
e.`salary`,
d.`dept_id`,
d.`dept_name`
FROM
# 表名 ,e d 分别是 表的别名
tbl_employee e,
tbl_dept d
WHERE
e.`dept_id` = d.`dept_id`
AND
d.dept_id = #{deptId}
</select>
- 通过部门id获取部门信息,及部门所属的员工信息【分步查询】
- 先通过部门id获取部门信息【dept_id,dept_name】
- 再通过员工id获取员工信息【id,last_name,email,salary,dept_id】
五.ResultMap相关标签及属性
- resultMap标签:自定义映射标签
- id属性:定义唯一标识
- type属性:设置映射类型
- resultMap子标签
- id标签:定义主键字段与属性关联关系
- result标签:定义非主键字段与属性关联关系
- column属性:定义表中字段名称(数据库列名)
- property属性:定义类中属性名称
- association标签:定义一对一的关联关系
- property:定义关联关系属性
- javaType:定义关联关系属性的类型
- select:设置分布查询SQL全路径
- column:设置分布查询SQL中需要的参数
- fetchType:设置局部延迟加载【懒加载】是否开启
- collection标签:定义一对多的关联关系
- property:定义一对一关联关系属性
- ofType:定义一对一关联关系属性类型
- fetchType:设置局部延迟加载【懒加载】是否开启
六.Mybatis 中分布查询
- 为什么使用分布查询【分步查询优势】?
- 将多表连接查询,改为【分步单表查询】,从而提高程序运行效率
association分步查询:
<!-- 自定义映射【员工与部门关系】-->
<!--type 主要查询的数据还是 员工的,所以用 employee-->
<resultMap id="empAndDeptResyltMapAssociationStep" type="employee">
<!-- 定义主键字段与属性关联关系-->
<!-- column 是字段,对应的是数据库的列名, property 是属性,对应的是 类的属性名-->
<id column="id" property="id"></id>
<!-- 定义非主键字段与属性关联关系-->
<result column="last_name" property="lastName"></result>
<result column="email" property="email"></result>
<result column="salary" property="salary"></result>
<!-- 为员工所属部门,自定义关联关系-->
<!-- 分步查询 -->
<association property="dept"
select="另一张表的mapper中查询方法的全路径"
column="dept_id 也就是两张表的关联值属性"
>
</association>
</resultMap>
<!-- 先通过员工id获取员工信息【id,last_name,email,salary,dept_id】-->
<!-- 再通过部门id获取部门信息【dept_id,dept_name】-->
<select id="selectEmpAndDeptByEmpIdAssociationStep" resultMap="empAndDeptResyltMapAssociationStep">
# 这个 resultMap 和 上面自定义映射的 resultMap 值一样
SELECT
id,
email,
last_name,
salary,
dept_id
FROM
# 表名 ,e d 分别是 表的别名
tbl_employee
WHERE
id= #{empId}
</select>
collection分步查询:
<!-- 自定义映射【员工与部门关系】-->
<!--type 主要查询的数据还是 员工的,所以用 employee-->
<resultMap id="deptAndEmpResultMapStep" type="dept">
<!-- 定义主键字段与属性关联关系-->
<!-- column 是字段,对应的是数据库的列名, property 是属性,对应的是 类的属性名-->
<id column="dept_id" property="deptId"></id>
<!-- 定义非主键字段与属性关联关系-->
<result column="dept_Name" property="deptName"></result>
<!-- 为员工所属部门,自定义关联关系-->
<!-- 分步查询 -->
<collection property="empList"
select="另一张表的mapper中查询方法的全路径"
column="dept_id 也就是两张表的关联值属性">
</collection>
</resultMap>
<!-- 通过部门id获取部门信息,及部门所属的员工信息【分步查询】-->
<!-- 先通过部门id获取部门信息【dept_id,dept_name】-->
<!-- 再通过员工id获取员工信息【id,last_name,email,salary,dept_id】-->
<select id="selectDeptAndEmpByDeptIdStep" resultMap="deptAndEmpResultMapStep">
# 这个 resultMap 和 上面自定义映射的 resultMap 值一样
SELECT
dept_id,
dept_name
FROM
# 表名 ,e d 分别是 表的别名
tbl_dept
WHERE
dept_id= #{deptId}
</select>
七.Mybatis延迟加载【懒加载】
- 需要时加载,不需要暂时不加载
- 优势:提升程序运行效率
① 全局设置 在分步查询的基础上,可以使用延迟加载来提升查询的效率,只需要在全局的 settings 中进行如下的配置:
② 局部设置 在 association 标签中也可以设置延迟加载,将覆盖全局配置
八.扩展
① 如果分步查询时,需要传递给调用的查询中有多个参数,则需要将多个参数封装成 Map 来进行传递,语法如下:{k1 = v1,k2 = v2 ...}
② 在所调用的查询方法取值时,就要参考 Map 的取值方式,需要严格的按照封装 map