resultMap: 自定义映射
若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
<!--
resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识
type:查询的数据要映射的实体类的类型
子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
association:设置多对一的映射关系
collection:设置一对多的映射关系
属性:
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名
-->
<resultMap id="empResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
</resultMap>
<select id="getEmpByEmpId" resultMap="empResultMap">
<!--select emp_id empId, emp_name empName, age, gender from t_emp where emp_id=#{empId}-->
select * from t_emp where emp_id = #{empId}
</select>
若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)
此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系
(a)通过为字段起别名的方式,保证和实体类中的属性名保持一致(如上面标注的做法)
(b)在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰
例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName
1、多对一映射处理
场景模拟:
查询员工信息以及员工所对应的部门信息。多个员工同属一个部门,一个部门包含多个员工。
表结构如下
t_emp:
t_dept:
sql语句为:
select * from t_emp left join t_dept on t_emp.dept_id = t_dept.dept_id
where t_emp.emp_id = 1;
第一种方式:级联方式
直接用dept.属性的方式查找对应字段
<resultMap id="empAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
<!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
select t_emp.*, t_dept.*
from t_emp
left join t_dept
on t_emp.dept_id = t_dept.dept_id
where t_emp.emp_id = #{empId};
</select>
第二种方式:使用association处理映射关系
association字段表示一对多的映射关系,主要处理实体类类型的属性(javaType)
<resultMap id="empAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
association: 处理一对多的映射关系(处理实体类类型的属性)
property: 设置需要处理映射关系的属性的属性名
javaType: 设置需要处理的属性的类型
-->
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
<!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
select t_emp.*, t_dept.*
from t_emp
left join t_dept
on t_emp.dept_id = t_dept.dept_id
where t_emp.emp_id = #{empId};
</select>
第三种方式:分步查询
分步查询的好处是可以延迟加载,在不需要用到第二步查询的信息时不加载第二步,降低内存消耗。
第一步(getEmpAndDeptByStepOne)通过emp_id查找对应行信息
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
property: 设置需要处理映射关系的属性的属性名
select: 设置分步查询的sql唯一标识
column: 将查询出的某个字段作为分步查询sql的条件
fetchType: 在开启了延迟加载的环境中,通过该属性设置当前的分步查询是的是否使用延迟加载
eager: 立即加载
lazy: 延迟加载
-->
<association property="dept" fetchType="eager"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id">
</association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where emp_id = #{empId}
</select>
第二步(getEmpAndDeptByStepTwo)
第一步查找到的信息包括一个dept实体类,通过对应t_dept表和t_emp表的dept_id字段将两个表格连接起来
<!--Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);-->
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
select * from t_dept where dept_id = #{deptId}
</select>
2、一对多映射处理
场景模拟: 查询部门id为1的员工信息
sql语句为:
select * from t_dept left join t_emp on t_dept.dept_id = t_emp.dept_id
where t_dept.dept_id = 1;
第一种方式:collection字段
<resultMap id="deptAndEmpResultMap" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<!--
ofType:设置集合类型的属性中存储的数据的类型
-->
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
</collection>
</resultMap>
<!--Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByDeptId" resultMap="deptAndEmpResultMap">
select *
from t_dept
left join t_emp
on t_dept.dept_id = t_emp.dept_id
where t_dept.dept_id = #{deptId};
</select>
第二种方式 分步查询
第一步 查询部门信息
<resultMap id="deptAndEmpResultMapByStep" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps"
select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="dept_id">
</collection>
</resultMap>
<!--Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpResultMapByStep">
select * from t_dept where dept_id = #{deptId}
</select>
第二步 根据部门id查询部门中的所有员工
<!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where emp_id = #{empId}
</select>