6. 自定义映射resultMap
6.1 代码结构
SqlSessionUtils.java、jdbc.properties、log4j.xml延用上面章节的。
6.1.1 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"/> <!--设置MyBatis的全局配置--> <settings> <!--将_自动映射为驼峰,emp_name:empName--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--开启延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> </settings> <typeAliases> <package name="com.atguigu.mybatis.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.atguigu.mybatis.mapper"/> </mappers> </configuration>
6.1.2 pojo
Dept
部门信息
package com.atguigu.mybatis.pojo; public class Dept { private Integer did; private String deptName; //省略get、set }
Emp
员工信息
package com.atguigu.mybatis.pojo; public class Emp { private Integer eid; private String empName; private Integer age; private String sex; private String email; //员工所属部门 private Dept dept; }
6.1.3 mapper
EmpMapper
package com.atguigu.mybatis.mapper; import com.atguigu.mybatis.pojo.Emp; public interface EmpMapper { /** * 查询所有的员工信息 */ List<Emp> getAllEmp(); /** * 查询员工以及员工所对应的部门信息 */ Emp getEmpAndDept(@Param("eid") Integer eid); /** * 通过分步查询查询员工以及员工所对应的部门信息 * 分步查询第一步:查询员工信息 */ Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid); /** * 通过分步查询查询部门以及部门中所有的员工信息 * 分步查询第二步:根据did查询员工信息 */ List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did); }
DeptMapper
package com.atguigu.mybatis.mapper; import com.atguigu.mybatis.pojo.Dept; public interface DeptMapper { /** * 通过分步查询查询员工以及员工所对应的部门信息 * 分步查询第二步:通过did查询员工所对应的部门 */ Dept getEmpAndDeptByStepTwo(@Param("did") Integer did); /** * 获取部门以及部门中所有的员工信息 */ Dept getDeptAndEmp(@Param("did") Integer did); /** * 通过分步查询查询部门以及部门中所有的员工信息 * 分步查询第一步:查询部门信息 */ Dept getDeptAndEmpByStepOne(@Param("did") Integer did); }
6.2 映射文件和测试编写
EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.atguigu.mybatis.mapper.EmpMapper"> <!-- resultMap:设置自定义映射关系 id:唯一标识,不能重复 type:设置映射关系中的实体类类型 子标签: id:设置主键的映射关系 result:设置普通字段的映射关系 属性: property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名 column:设置映射关系中的字段名,必须是sql语句查询出的字段名 --> <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> <!--处理多对一映射关系方式一:级联属性赋值--> <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> <!--处理多对一映射关系方式二:association--> <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:需要处理多对的映射关系的属性名 javaType:该属性的类型 --> <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.did = t_dept .did where t_emp.eid = #{eid} </select> <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:设置分布查询的条件 fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果 fetchType="lazy|eager":lazy表示延迟加载,eager表示立即加载 --> <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="did" fetchType="eager"></association> </resultMap> <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);--> <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap"> select * from t_emp where eid = #{eid} </select> <select id="getAllEmpOld" resultType="Emp"> <!--select eid,emp_name empName,age,sex,email from t_emp--> select * from t_emp </select> <!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);--> <select id="getDeptAndEmpByStepTwo" resultType="Emp"> select * from t_emp where did = #{did} </select> </mapper>
ResultMapTest.java
package com.atguigu.mybatis.test; import com.atguigu.mybatis.mapper.DeptMapper; import com.atguigu.mybatis.mapper.EmpMapper; import com.atguigu.mybatis.pojo.Dept; import com.atguigu.mybatis.pojo.Emp; import com.atguigu.mybatis.utils.SqlSessionUtils; public class ResultMapTest { /** * 解决字段名和属性名不一致的情况: * a>为字段起别名,保持和属性名的一致 * b>设置全局配置,将_自动映射为驼峰 * <setting name="mapUnderscoreToCamelCase" value="true"/> * c>通过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> * * 处理多对一的映射关系: * a>级联属性赋值 * b>association * c>分步查询 * * 处理一对多的映射关系 * a>collection * b>分步查询 */ @Test public void testGetEmpAndDeptByStep(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp emp = mapper.getEmpAndDeptByStepOne(3); System.out.println(emp.getEmpName()); System.out.println("+++++++++++++++++++++++++++++++++++++"); System.out.println(emp.getDept()); } @Test public void testGetEmpAndDept(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp emp = mapper.getEmpAndDept(3); System.out.println(emp); } @Test public void testGetAllEmp(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); List<Emp> list = mapper.getAllEmp(); list.forEach(emp -> System.out.println(emp)); } @Test public void testGetDeptAndEmp(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.getDeptAndEmp(1); System.out.println(dept); } @Test public void testGetDeptAndEmpByStep(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.getDeptAndEmpByStepOne(1); System.out.println(dept.getDeptName()); } }
6.2.1 resultMap处理字段和属性的映射关系
resultMap:设置自定义映射
id:表示自定义映射的唯一标识,不能重复
type:查询的数据要映射的实体类的类型
id:设置主键的映射关系
result:设置普通字段的映射关系
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名
EmpMapper.xml
若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来
<!--resultMap:设置自定义映射 id:设置唯一标识,不能重复 type:设置实体类类型 --> <resultMap id="empResultMap" type="Emp"> <!--id:设置主键映射关系 property:设置实体类的属性名 column:设置表中对应的字段--> <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>
@Test //获取所有的员工 public void testGetAllEmp(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); List<Emp> list = mapper.getAllEmp(); list.forEach(emp -> System.out.println(emp)); }
若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系
- 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
<!--List<Emp> getAllEmp();--> <select id="getAllEmp" resultType="Emp"> select eid,emp_name empName,age,sex,email from t_emp </select>
- 可以在MyBatis的核心配置文件中的
setting
标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
6.2.2 多对一映射处理
查询员工信息以及员工所对应的部门信息
public class Emp { private Integer eid; private String empName; private Integer age; private String sex; private String email; //加一行这个 员工所属的部门 多个员工对应一个部门 private Dept dept; //...构造器、get、set方法等 }
6.2.2.1 级联方式处理映射关系
<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>
@Test //获取员工信息 和这个员工所属的部门 public void testGetEmpAndDept(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp emp = mapper.getEmpAndDept(3); System.out.println(emp); }
6.2.2.2 使用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>
6.2.2.3 分步查询
1. 查询员工信息
- select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
- column:设置分步查询的条件
//EmpMapper里的方法 /** * 通过分步查询,员工及所对应的部门信息 * 分步查询第一步:查询员工信息 * @param * @return com.atguigu.mybatis.pojo.Emp */ 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:设置分布查询的条件 fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果 fetchType="lazy|eager":lazy表示延迟加载,eager表示立即加载 --> <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="did"></association> </resultMap> <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);--> <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap"> select * from t_emp where eid = #{eid} </select>
2. 查询部门信息
//DeptMapper里的方法 /** * 通过分步查询,员工及所对应的部门信息 * 分步查询第二步:通过did查询员工对应的部门信息 * @param * @return com.atguigu.mybatis.pojo.Emp */ Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
<!--此处的resultMap仅是处理字段和属性的映射关系--> <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>
MyBatis(三)(2)+https://developer.aliyun.com/article/1556671