ResultType是默认映射,要求字段名要和属性名一致,但是如果我们数据库中的表的字段名和实体类的属性名不一致怎么办呢?这个时候就得用ResultMap来自定义映射
前期准备
先准备两张表,一张是员工表,一张部门表
1.解决字段名和属性名不一致的情况
1.1方法一 为字段起别名,保持属性名和字段名的一致
当我们写的实体类的属性遵循驼峰,属性名和字段名不一致的话,如果我们使用sql语句的返回值类型用的是resultType的话,是差不多数据的
<select id="getAllEmp" resultType="com.atguigu.mybatis.pojo.Emp"> select * from t_emp; </select>
我们可以看到empName是没有数据的
解决方法一,sql语句查询的时候使用别名,别名要和属性名一致> <select id="getAllEmp" resultType="com.atguigu.mybatis.pojo.Emp"> select eid,emp_name empName,age,sex,email from t_emp; </select>
这样子可以查到数据
1.2方法二 设置全局配置,把下划线映射为驼峰
方法二 使用settings进行全局映射
<!-- 设置全局属性值--> <settings> <!-- 把下划线映射为驼峰 emp_name映射成empName,em_pname映射成emPname--> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
> <select id="getAllEmp" resultType="com.atguigu.mybatis.pojo.Emp"> -- select eid,emp_name empName,age,sex,email from t_emp; select * from t_emp; </select>
1.3方法三 使用ResultMap进行自定义映射
设置字段和属性的关系
<!-- resultMap:设置自定义映射关系
id:唯一标识
type:设置映射关系中的实体类类型-->
<resultMap id="empResultMap" type="Emp">
<!-- id设置主键的映射关系,result设置普通字段的映射关系
property设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名
column:设置映射关系中的字段名,必须是sql语句查询出的字段名-->
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<select id="getAllEmp" resultMap="empResultMap">
select *
from t_emp;
</select>
我们都知道数据库中表和表是有关系的,那么它们所对应的实体类,我们要怎样才能使他们有关系呢
2.多对一的映射关系
比如说两张表emp,dept,emp表中有dept表中的部门编号属性,通过这个属性可以查询对应的信息,我们就可以在emp表所对应的实体类中创建对象dept,来表示当前员工所对应的部门对象,我们知道一个部门有多个员工,我们就可以在部门表对应的实体类中设置一个属性,表示员工的集合。
但是这里有一个问题需要我们来解决,我们在mybatis中,通过字段名和属性进行映射,但是,举个例子:我们想要查询员工表的部门编号和部门表的部门编号相等的员工信息,员工表对应的实体类中属性是Dept dept,但是查询出来的结果中,会有部门名字和部门编号,这个时候就无法进行映射,那要怎么解决?接下来给出具体解决方法
2.1方法一 级联属性赋值
2.2方法二 通过assocation解决多对一问题
<resultMap id="empAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="deptName" column="dept_name"></id>
<id property="did" column="did"></id>
</association>
</resultMap>
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
SELECT *
FROM t_emp
LEFT JOIN t_dept ON t_emp.did=t_dept.did
WHERE t_emp.did=2;
</select>
我们之前的方法都是通过一条sql语句查询多张表,把数据查询出来,那么我们能不能通过多条sql语句,一步一步查询出来呢?
我们可以先把员工信息查询出来,然后根据员工信息的部门编号把对应的部门信息查询出来,然后把查询出来的部门信息赋值给我们的dept属性,这个方法就是分步查询
2.3方法三 分步查询(用得比较多)
<font size=4 color="bluefeafefgrbtnhyjythhrsgaeqwegq">**select**设置分步查询的sql的唯一标识(命名空间.SQLID 或mapper接口的全类名.方法名)
**column**设置分步查询的条件,比如说我们想要查询部门信息,那么应该是根据部门编号来查询的
我们查询到了员工信息,那要怎么根据这个信息来查询部门信息呢,那就得根据它们共有的字段did属性也就是部门编号来查询
在这个sql语句里面我们查询的是员工信息,但是dept的信息要根据另外一条sql语句来查询
所以这里要通过select属性来说明我们是通过哪一个sql查询出来的
<resultMap id="empAndDeptByStepResultMapOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<!-- column设置分步查询的条件,比如说我们想要查询部门信息,那么应该是根据部门编号来查询的
我们查询到了员工信息,那要怎么根据这个信息来查询部门信息呢,那就得根据它们共有的字段did属性也就是部门编号来查询
在这个sql语句里面我们查询的是员工信息,但是dept的信息要根据另外一条sql语句来查询
所以这里要通过select属性来说明我们是通过哪一个sql查询出来的-->
<association property="dept"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"></association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMapOne">
select * from t_emp where eid= #{eid};
</select>
<select id="getEmpAndDeptByStepTwo" resultType="com.atguigu.mybatis.pojo.Dept">
select * from t_dept where did= #{did};
</select>
测试结果
这个时候大家可能就会有这样的疑惑,我们之前的方法明明可以通过一个SQL语句来解决问题,为什么非得用两个sql语句呢?这样子不是变得更加复杂了吗?其实我们可以发现这两个sql语句分开,各自都是一个功能
分步查询的好处是延迟加载,在mybatis中,延迟加载默认是不开启延迟加载的,我们如果想要实现延迟加载,就必须在核心配置文件中设置全局配置信息(settings标签)。
<settings>
<!-- 把下划线映射为驼峰 emp_name映射成empName,em_pname映射成emPname-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
lazyLoadingEnabled:延迟加载的全局开关,当开启时,所有关联对象(分步查询的第一步,第二步......)都会延迟加载
开启延迟加载后,我们会发现只执行查询员工sql语句,没有执行dept的sql语句
如果关闭延迟加载,我们会发现我们本来只是想要查询员工的名字,它还会执行查询部门的sql语句
aggresslveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每一个属性会按需加载
延迟加载指的是当我们访问哪一些信息,它就会去执行相应的sql,如果没有访问,则没有执行
此时就可以实现按需加载,获取的数据是什么就只会执行相应的sql,此时可以通过assocation和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载) | eager(立即加载)"
select:设置分步查询的sql唯一标识
column:设置分步查询的条件
fetchtype:当开启了全局的延迟加载以后,可以通过这个属性手动控制延迟加载的效果,如果没有开启延迟加载,那么这个属性可以取的两个值都表示立即加载
3.一对多的映射关系
3.1方法一 通过collection
<resultMap id="deptAndEmpResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<!-- collection:处理一对多的映射关系-->
<!-- ofTypeL:表示该属性所对应的集合中存储数据的类型-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<select id="getDeptAndEmp" resultMap="deptAndEmpResultMap">
select *
from t_dept
left join t_emp on t_dept.did = t_emp.did
where t_dept.did = #{did}
</select>
collection:处理一对多的映射关系-->
ofType:表示该属性所对应的集合中存储数据的类型
3.2分步查询
先根据部门编号did查询出部门信息,然后再查询出所有员工信息
package com.atguigu.mybatis.mapper;
import com.atguigu.mybatis.pojo.Dept;
import org.apache.ibatis.annotations.Param;
/**
* @author zengyihong
* @create 2022--04--03 14:40
*/
public interface DeptMapper {
Dept getDeptAndEmp(@Param("did") Integer did);
/**
* 分步查询部门以及部门中所有的员工信息
* 分步查询第一步:查询部门信息
*/
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
}
package com.atguigu.mybatis.mapper;
import com.atguigu.mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author zengyihong
* @create 2022--04--03 14:40
*/
public interface EmpMapper {
/**
* 分步查询部门以及部门中所有的员工信息
* 分步查询第二步:根据did查询员工信息
*/
List<Emp> getDeptAndEmpByStepTwo(@Param("did")Integer did)
}
deptmapper.xml
<resultMap id="deptAndEmpResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<!-- collection:处理一对多的映射关系-->
<!-- ofType:表示该属性所对应的集合中存储数据的类型-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<resultMap id="deptAndEmpByStepResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps"
select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did">
</collection>
</resultMap>
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpByStepResultMap">
select * from t_dept where did = #{did};
</select>
empmapper.xml
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select *
from t_emp
where did = #{did};
</select>