自定义映射resultMap:
resultMap处理字段和属性的映射关系
- resultMap:设置自定义映射关系
- 属性:
- id:表示自定义映射的唯一标识,不能重复
- type:查询的数据要映射的实体类的类型
- 子标签:
- id:设置主键的映射关系
- result:设置普通字段的映射关系
- 子标签属性:
- property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名
- column:设置映射关系中的字段名,必须是SQL语句查询出来的字段名
- 属性:
- –》若字段名和实体类中的属性名不一致,可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来
<resultMap id="empResultMap" 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>
</resultMap>
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>
-
–》若字段名和实体类中的属性名不一致,因为字段名符合数据库的规则(使用 _ ),实体类中的属性名符合Java的规则(使用 驼峰 )。此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系
1、可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
<!--List<Emp> getAllEmp();--> <select id="getAllEmp" resultType="Emp"> select eid,emp_name empName,age,sex,email from t_emp </select>
2、可以在MyBatis的核心配置文件中的
setting
标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
多对一映射处理:
查询员工信息以及员工所对应的部门信息
public class Emp {
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
//...构造器、get、set方法、toString方法等
}
处理多对一映射关系的方式一:级联属性赋值
<resultMap id="empAndDeptResultMapOne" 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>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>
处理多对一映射关系的方式二:association标签
- association:处理多对一的映射关系
- property:需要处理多对一映射关系的属性名
- javaType:该属性的类型
<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="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>
处理多对一映射关系的方式三:分步查询
分步查询第一步. 查询员工信息
// EmpMapper.xml里的方法
/**
* 通过分步查询,查询员工以及员工所对应的部门信息
* 分步查询第一步:查询员工信息
*/
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
<resultMap id="empAndDeptByStepResultMap" 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>
<!--
select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
column:设置分步查询的条件
-->
<association property="dept"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"></association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where eid = #{eid}
</select>
分步查询第一步. 查询部门信息
//DeptMapper里的方法
/**
* 通过分步查询,查询员工以及员工所对应的部门信息
* 分步查询第二步:通过did查询员工所对应的部门
*/
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
<!--此处的resultMap仅仅是处理字段(dept_name)和属性(deptName)的映射关系-->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
select * from t_dept where did = #{did}
</select>
一对多映射处理:
public class Dept {
private Integer did;
private String deptName;
private List<Emp> emps;
//...构造器、get、set方法等
}
通过collection标签解决一对多的映射关系:
- collection:用于处理一对多的映射关系
- ofType:表示该属性对应的集合中存储数据的类型(就是上方List emps定义的集合的类型)
<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>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<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>
通过分步查询解决一对多的映射关系:
1. 根据部门id查询部门信息
/**
* 通过分步查询 查询部门以及部门中所有的员工信息
* 分步查询第一步:查询部门信息
*/
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<!--
select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
column:设置分步查询的条件
-->
<collection property="emps"
select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"></collection>
</resultMap>
<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
select * from t_dept where did = #{did}
</select>
2. 根据部门id查询部门中的所有员工
/**
* 通过分步查询 查询部门以及部门中所有的员工信息
* 分步查询第二步:根据did查询员工信息
* 类型定义为:List<Emp> 是因为在Dept的model类中定义的emps的类型就是这个
*/
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where did = #{did}
</select>
总结:
多对一:对应对象!(需要在实体类中创建"一"的对象,就相当于上方在Emp类中创建Dept对象)!
一对多:对应集合!(需要在实体类中创建存储"多"的集合,就相当于上方在Dept类中创建List集合)!
延迟加载:
- 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
- lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
- aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
- 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载(使延迟加载可控),fetchType=“lazy(延迟加载(默认))|eager(立即加载)”
<!--核心配置文件(mybatis-config.xml)-->
<settings>
<!--开启延迟加载,这样在Mybatis范围内全部都实现延迟加载!-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
@Test
public void getEmpAndDeptByStepOne() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName()); // 只获取员工姓名!
}
- 关闭延迟加载,两条SQL语句都运行了
- 开启延迟加载,只运行获取emp的SQL语句
@Test
public void getEmpAndDeptByStepOne() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName());
System.out.println("----------------");
System.out.println(emp.getDept());
}
-
关闭延迟加载:
-
开启后,需要用到查询dept的时候才会调用相应的SQL语句
<resultMap id="empAndDeptByStepResultMap" 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>
<!--
fetchType:当开启了全局的延迟加载之后(必须要先开启全局延迟加载,否则下面的两个属性都是立即加载的意思),可以通过该属性手动控制延迟加载的效果.
fetchType="lazy(延迟加载(默认))|eager(立即加载)"
-->
<association property="dept"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"
fetchType="lazy"></association>
</resultMap>