8.1、resultMap处理字段和属性的映射关系
如果字段名和实体类中的属性名不一致的情况下,可以通过resultMap设置自定义映射。
⑴可以通过为字段起别名的方式,别名起成和属性名一致。保证字段名和实体类中的属性名一致
< select id ="getEmpByEmpId" resultType ="emp" > select emp_id empId,emp_name empName,age,sex from emp where emp_id = #{empId} </ select >
⑵如果字段名和实体类中的属性名不一致的情况下,但是字段名符合数据库的规则(使用_),实体类中使用的属性名符合java的规则(使用驼峰命名),可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase ,可以在查询表中的数据时,自动将带下划线“_”的字段名转为驼峰命名
user_name:userName
emp_id:empId
< settings > <!-- 将数据库字段名的下划线映射为驼峰 --> < setting name ="mapUnderscoreToCamelCase" value ="true" /> </ settings >
<!--Emp getEmpByEmpId(@Param("empId") Integer empId);--> < select id ="getEmpByEmpId" resultType ="emp" > select * from emp where emp_id = #{empId} </ select >
⑶使用resutlMap自定义映射处理
<!-- resultMap: 设置自定义的映射关系 id: 唯一标识 type: 处理映射关系的实体类的类型 一般使用 MyBatis 的别名 常用的标签 id: 处理主键和实体类中属性的映射关系 result: 处理普通字段和实体类中属性的映射关系 column: 设置映射关系中的字段名,必须是 sql 查询出的某个字段 property: 设置映射关系中的属性的属性名,必须是处理的实体类型中的属性名 --> < resultMap id ="empReslutMap" type ="emp" > < id property ="empId" column ="emp_id" ></ id > < result property ="empName" column ="emp_name" ></ result > < result property ="age" column ="age" ></ result > < result property ="sex" column ="sex" ></ result > </ resultMap >
8.2、一对一映射处理
人与身份证号
1、级联方式处理
/** * 根据 id 查询人员信息 * @param id * @return */ Person findPersonById ( @Param ( "id" ) Integer id);
<!-- Person findPersonById(Integer id);--> < select id ="findPersonById" resultMap ="IdCardWithPersonResult" > SELECT person.*,idcard.code FROM person,idcard WHERE person.card_id=idcard.id AND person.id=#{id} </ select > < resultMap id ="IdCardWithPersonResult" type ="person" > < id property ="id" column ="id" ></ id > < result property ="name" column ="name" ></ result > < result property ="age" column ="age" ></ result > < result property ="sex" column ="sex" ></ result > < result property ="card.id" column ="id" ></ result > < result property ="card.code" column ="code" ></ result > </ resultMap >
a ssociation
< resultMap id ="IdCardWithPersonResult2" type ="person" > < id property ="id" column ="id" ></ id > < result property ="name" column ="name" ></ result > < result property ="age" column ="age" ></ result > < result property ="sex" column ="sex" ></ result > < association property ="card" javaType ="IdCard" > < id property ="id" column ="id" ></ id > < result property ="code" column ="code" ></ result > </ association > </ resultMap >
3、分步查询
<!-- 分步查询第一步 --> <!-- Person findPersonById3(@Param("id") Integer id);--> < select id ="findPersonById3" resultMap ="IdCardWithPersonResult3" > select * from person where id=#{id} </ select > < resultMap id ="IdCardWithPersonResult3" type ="person" > < id property ="id" column ="id" ></ id > < result property ="name" column ="name" ></ result > < result property ="age" column ="age" ></ result > < result property ="sex" column ="sex" ></ result > <!-- association :处理一对一或者多对一的映射关系 ( 处理的实体类类型的属性 ) property :设置需要处理映射关系的属性的属性名 javaType: 设置要处理的属性的类型 column :第一步传递给第二步的字段,映射关系的表关联的字段 --> < association property ="card" javaType ="IdCard" column ="card_id" select ="com.qcby.mybatis.mapper.IdCardMapper.findCodeById" > </ association > </ resultMap >
<!-- 分步查询的第二步 --> <!--IdCard findCodeById(@Param("id") Integer id);--> < select id ="findCodeById" resultType ="idcard" > SELECT * from idcard where id=#{id} </ select >
8.3、多对一映射处理
场景模拟:
查询员工信息以及员工所对应的部门信息
使用 resultMap自定义映射处理 处理多对一的映射关系:
1、级联方式处理
/** * 获取员工以及所对应的部门信息 * @param empId * @return */ Emp getEmpAndDeptByEmpId ( @Param ( "empId" ) Integer empId);
<!-- Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);--> < select id ="getEmpAndDeptByEmpId" resultMap ="empAndDeptResultMap" > SELECT emp.*,dept.* FROM emp LEFT JOIN dept ON emp.dept_id=dept.dept_id WHERE emp.emp_id=#{empId} </ select >
< 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 ="sex" property ="sex" ></ result > < result column ="dept_id" property ="dept.deptId" ></ result > < result column ="dept_name" property ="dept.deptName" ></ result > </ resultMap >
@Test public void testGetEmpAndDeptByEmpId (){ Emp emp = empMapper .getEmpAndDeptByEmpId( 1 ); System . out .println( emp ); }
2、a ssociation
< 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 ="sex" property ="sex" ></ result > < association property ="dept" javaType ="dept" > < id column ="dept_id" property ="deptId" /> < result column ="dept_name" property ="deptName" ></ result > </ association > </ resultMap >
3、分步查询
① 根据员工id 查询员工信息
emp接口中
/** * 通过分步查询来查询员工以及所对应部门信息的第一步 * @param empId * @return */ Emp getEmpAndDeptByStepOne ( @Param ( "empId" ) Integer empId);
dept接口中
/** * 通过分步查询来查询员工以及所对应部门信息的第二步 * @param deptId * @return */ Dept getEmpAndDeptByStepTwo ( @Param ( "deptId" ) Integer deptId);
emp映射文件中
<!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);--> < select id ="getEmpAndDeptByStepOne" resultMap ="empAndDeptByStepResultMap" > select * from emp where emp_id = #{empId} </ select >
< 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 ="sex" property ="sex" ></ result > < association property ="dept" column ="dept_id" select ="com.qcby.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" ></ association > </ resultMap >
dept映射文件中
<!--Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);--> < select id ="getEmpAndDeptByStepTwo" resultType ="Dept" > select * from dept where dept_id = #{deptId} </ select >
测试
@Test public void testGetEmpAndDeptByStepOne (){ Emp emp = empMapper .getEmpAndDeptByStepOne( 1 ); System . out .println( emp ); }
分步查询的优点:可以实现 延迟加载(懒加载) ,但是必须在核心配置文件中设置全局配置信息:
lazyLoadingEnabled :延迟加载的全局开关。当开启时,所有管理对象都会延迟加载
aggressiveLazyLoading :当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载,此时就可以实现按需加载,获取的数据是什么,就会执行相应的sql语句
此时可以通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)| eager(立即加载) ”
8.4、一对多映射处理 部门 -->员工
没有级联方式的查询 ,只有collection 和分步查询
8.4.1 collection
dept接口
/** * 查询部门以及部门中的员工信息 * @param deptId * @return */ Dept getDeptAndEmpByDeptId ( @Param ( "deptId" ) Integer deptId);
dept映射文件中
<!--Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);--> < select id ="getDeptAndEmpByDeptId" resultMap ="deptAndEmpResultMap" > SELECT * FROM dept LEFT JOIN emp ON dept.dept_id=emp.dept_id WHERE dept.dept_id=#{deptId} </ select > < 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 ="sex" property ="sex" ></ result > </ collection > </ resultMap >
测试方法
@Test public void testGetDeptAndEmpByDeptId (){ Dept dept = deptMapper .getDeptAndEmpByDeptId( 1 ); System . out .println( dept ); }
8.4.1 分步查询
⑴查询部门信息
/** * 通过分步查询进行查询部门及部门中的员工信息的第一步:查询部门信息 * @param deptId * @return */ Dept getDeptAndEmpBySetpOne ( @Param ( "deptId" ) Integer deptId);
<!-- Dept getDeptAndEmpBySetpOne(@Param("deptId") Integer deptId);--> < select id ="getDeptAndEmpBySetpOne" resultMap ="deptAndEmpResultMapByStep" > select * from dept where 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" column ="dept_id" select ="com.qcby.mybatis.mapper.EmpMapper.getDeptAndEmpBySetpTwo" ></ collection > </ resultMap >
⑵查询员工信息
/** * 通过分步查询进行查询部门及部门中的员工信息的第二步:查询员工信息 * @param deptId * @return */ List < Emp > getDeptAndEmpBySetpTwo ( @Param ( "deptId" ) Integer deptId);
<!-- List<Emp> getDeptAndEmpBySetpTwo(@Param("deptId")Integer deptId);--> < select id ="getDeptAndEmpBySetpTwo" resultType ="emp" > select * from emp where dept_id = #{deptId} </ select >
⑶测试方法
@Test public void testGetDeptAndEmpBySetp (){ Dept dept = deptMapper .getDeptAndEmpBySetpOne( 2 ); System . out .println( dept ); }
8.5、多对多映射关系
商品和订单两者之间的关系 一种商品存在多个订单中、一个订单存在多个商品
创建一个中间表来描述两者的关联关系
商品的表结构
订单的表结构
中间表
8.5.1、pojo
8.5.2、collection
8.5.3 分步查询
⑴查询订单信息
/** * 通过分步查询进行查询订单以及订单中的商品信息的第一步 * @param id * @return */ List < Orders > findOrdersWithProduct2 ( @Param ( "id" ) Integer id);
<!-- List<Orders> findOrdersWithProduct2(@Param("id") Integer id);--> < select id ="findOrdersWithProduct2" resultMap ="OrdersWithProductResult2" > select * from orders where id = #{id} </ select > < resultMap id ="OrdersWithProductResult2" type ="orders" > < id column ="id" property ="id" ></ id > < result column ="number" property ="number" ></ result > < collection property ="productList" column ="id" ofType ="product" select ="com.qcby.mybatis.mapper.ProductMapper.findProductById" > </ collection > </ resultMap >
⑵查询商品信息
/** * 通过分步查询进行查询订单以及订单中的商品信息的第二步 * @param id * @return */ List < Product > findProductById ( @Param ( "id" ) Integer id);
<!--List<Product> findProductById(@Param("id") Integer id);--> < select id ="findProductById" resultType ="product" > select * from product where id in( select product_id from ordersitem where orders_id = #{id} ) </ select >
⑶测试
@Test public void testFindOrdersWithProduct2 (){ List < Orders > orders = ordersMapper .findOrdersWithProduct2( 1 ); orders .forEach( System . out ::println); }