mybatis-- resultMap用法

resultMap 可以看https://www.bilibili.com/video/av21272940/   这里的讲解很细致


1. 当表的字段与实体类的属性不一致

例如我的表里的字段是emp_name     javaBean类里面是name, 这时mybatis自动映射不能帮忙了

1. 将 name  改为 empName   就可以

2. 用resultMap来映射

在mapper.xml文件里面

 <resultMap type="org.mybatis.pojo.Employee" id="empMap">
         <!-- 用id属性来映射主键字段 -->
         <id property="id" column="id"/>
         
         <!-- 用result属性来映射非主键字段 -->
         <result property="name" column="emp_name"/>
         <result property="age" column="age"/>
         <result property="did" column="d_id"/>
</resultMap>
<select id="selectById" resultMap="empMap">  //resultMap 和 和上面的id="empMap"对应
		select * from emp where id=#{id}
</select>

注意  insert  update  delete是没有resultType和resultMap属性的,下面的图可以看到

http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

2. 一对多时 如何使用?

(1)使用级联属性

<resultMap type="org.mybatis.pojo.Employee" id="joinMap">
		<!-- 用id属性来映射主键字段 -->
		<id column="id" property="id" />
		<!-- 用result属性来映射非主键字段 -->
		<result column="emp_name" property="empName" />
		<result column="age" property="age" />
		<result  column="did" property="dept.id"/>
		<result  column="dept_name" property="dept.deptName"/>
	</resultMap>

<!-- 当我要联表查询   一个部门有多个员工时   public Employee selectWithDept(Integer id); -->
		<select id="selectWithDept" resultMap="joinMap">
		select	e.id id,
				e.emp_name emp_name,
				e.age age,
				e.d_id d_id,
				d.id did,
				d.dept_name dept_name
				FROM emp e, dept d
				WHERE
				e.d_id = d.id
				AND e.id = #{id}
		</select>

这里column 与你的SQL语句中要查询的列要对应  ,property是对应的POJO属性对应

我将这里的列名 改掉 ,则会查不出对应的部门信息


(2)可以通过  association来替代级联

<!--  association可以指定联合的javaBean对象
		property="dept":指定哪个属性是联合的对象
		javaType:指定这个属性对象的类型[不能省略]
		-->

<resultMap type="org.mybatis.pojo.Employee" id="myMap">
		<!-- 用id属性来映射主键字段 -->
		<id column="id" property="id" />
		<!-- 用result属性来映射非主键字段 -->
		<result column="emp_name" property="empName" />
		<result column="age" property="age" />
		<association property="dept" javaType="org.mybatis.pojo.Department">
			<result  column="did" property="id"/>
			<result  column="dept_name" property="deptName"/>
		</association>
	</resultMap>

3)可以通过  association实现分步查询

绑定mapper出现BindingException 要注意<mapper namespace="org.mybatis.mapper.DepartmentMapper">不要写成了POJO的全类名

<!-- 使用association进行分步查询:
1、先按照员工id查询员工信息
2、根据查询员工信息中的d_id值去部门表查出部门信息
3、部门设置到员工中;
-->

public interface EmployeeMapper {
	
	public Employee getEmpByIdStep(Integer id);
<resultMap type="org.mybatis.pojo.Employee" id="assMap">
		<!-- 用id属性来映射主键字段 -->
		<id column="id" property="id" />
		<!-- 用result属性来映射非主键字段 -->
		<result column="emp_name" property="empName" />
		<result column="age" property="age" />
		<result column="d_id" property="did" />
		<!-- association定义关联对象的封装规则
	 		select:表明当前属性是调用select指定的方法查出的结果
	 		column:指定将哪一列的值传给这个方法
	 		
	 		流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
	 	 -->
	<association property="dept"
		select="org.mybatis.mapper.DepartmentMapper.findDeptById"
		column="d_id">
	</association>
</resultMap>

<select id="getEmpByIdStep" resultMap="assMap">
	select * from emp where id=#{id}
</select>

Department里面

public interface DepartmentMapper {
	public Department findDeptById(Integer id);
}
<?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="org.mybatis.mapper.DepartmentMapper">
 	<select id="findDeptById" resultType="org.mybatis.pojo.Department">
 		select  id , dept_name deptName from dept  where id=#{id}
 	</select>
 
 </mapper>

最后的单元测试

@Test
	public void test3() throws Exception{
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		//2.
		SqlSession openSession = sqlSessionFactory.openSession();
		try {
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Employee emp = mapper.getEmpByIdStep(2);
			System.out.println(emp);
			System.out.println(emp.getDept());
		} finally {
			openSession.close();
		}
	}

可以看到控制台发了两个SQL  ,Employee显示出了全部的内容



(4)延迟加载(懒加载)

association和collection还具备延迟加载的功能

在mybatis-config文件中配置下面的

lazyLoadingEnabled

默认是false)

延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。

true | false false

aggressiveLazyLoading

(默认是false,  true in ≤3.4.1)

当开启时,任何方法的调用都会加载该对象的所有属性

。否则,每个属性会按需加载(参考lazyLoadTriggerMethods).

我的mybatis版本3.4.1的    aggressiveLazyLoading默认是true,需要改为false
<settings>
		<setting name="mapUnderscoreToCamelCase" value="true"/>
		 
    	 <setting name="lazyLoadingEnabled" value="true"/>
    	
    	<setting name="aggressiveLazyLoading" value="false"/> 
</settings>
将这个<setting name="aggressiveLazyLoading" value="false"/>注释掉 只开启一个  依然是发送的两个SQL
开启延时加载最好是同时设置这两个,
	@Test
	public void test3() throws Exception{
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		//2.
		SqlSession openSession = sqlSessionFactory.openSession();
		try {
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Employee emp = mapper.getEmpByIdStep(2);
			
			System.out.println(emp.getEmpName());
			
		} finally {
			openSession.close();
		}
	}

没开启就会发送2个SQL


开启后只发送了一条SQL


(5) resultMap高级映射collection的使用

当我要查询 一个部门的所有员工时 ,比如需要查出开发部里的全部员工 , 返回的是查询的部门中包含多名员工

这时将关联的员工信息封装起来     需要用collection来处理

DepartmentMapper.xml里面设置resultMap

<!--嵌套结果集的方式 使用collection标签定义关联的集合类型的属性封装规则  -->
 <resultMap type="org.mybatis.pojo.Department" id="myCollection">
 	<id column="did" property="id"/>
 	<result column="dept_name" property="deptName"/>
 	<!--collection里面定义关联集合类型属性的封装 
 		odType:指定集合里面元素的类型
 	 -->
 	<collection property="emps" ofType="org.mybatis.pojo.Employee">
 		<id column="eid" property="id"/>
 		<result column="emp_name" property="empName"/>
 		<result column="age" property="age"/>
 	</collection>
 </resultMap>
 
 <select id="getDeptByIdPlus" resultMap="myCollection">
	select d.id did,dept_name dept_name , e.id eid, e.emp_name emp_name,e.age age
	from dept d
	LEFT JOIN  emp e
	on d.id=e.d_id
	WHERE d.id=#{id}
 </select>

DepartmentMapper.java  接口中定义这个方法

public Department getDeptByIdPlus(Integer id);

这里的collection用于封装查询到的Employee信息

<!--collection里面定义关联集合类型属性的封装 
 		odType:指定集合里面元素的类型
 	 -->

这里要先在Department POJO类   加上一个集合属性 

public class Department {
	private Integer id;
	private String deptName;
	private List<Employee> emps;//加上这个集合属性

这样就可以查到  一个部门 下的 所有员工

@2   与association类似,collection同样支持分段查询 以及延迟加载

分段查询: 同样地 要查询一个部门下的所有员工,可以分阶段  先查部门  再查询员工

1.首先在两个mapper加上接口方法

public Department getDeptByIdStep(Integer id); ===》》  DepartmentMapper
public List<Employee> getEmpsByIdStep(Integer deptId);   ===》》  EmployeeMapper

2.对应的Departmentmapper.xml   以及 EmployeeMapper.xml

<!--collection分段查询  -->
 <resultMap type="org.mybatis.pojo.Department" id="stepCollection">
 	<id column="id" property="id"/>
	<result column="dept_name" property="deptName"/> 
	<collection property="emps"
		    select="org.mybatis.mapper.EmployeeMapper.getEmpsByIdStep"  
		    column="{deptId=id}">
	
	</collection>
 </resultMap>
 
 <!-- public Department getDeptByIdStep(Integer id); -->
 <select id="getDeptByIdStep" resultMap="stepCollection">
 	select id,dept_name from dept where id=#{id}
 </select>
<select id="getEmpsByIdStep" resultType="org.mybatis.pojo.Employee">
	select * from emp where d_id=#{deptId}
</select>
通过测试,可以看到发送了两个SQL

对于延迟加载   是按需加载,若只要查询部门名,就只会发一条SQL

<!-- 扩展:多列的值传递过去:
将多列的值封装map传递;
column="{key1=column1,key2=column2}"
        fetchType="lazy":表示使用延迟加载;
- lazy:延迟

- eager:立即  //即使全局配置了延迟加载  也可以在这里让其立即加载

@3 discriminator鉴别器  (用的比较少 了解下)

<!-- =======================鉴别器============================ -->
<!-- <discriminator javaType=""></discriminator>
鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为
封装Employee

如果查出的是女生:就把部门信息查询出来,否则不查询;
如果是男生,把last_name这一列的值赋值给email;

-->

<resultMap type="org.mybatis.pojo.Employee" id="DisMap">
		<!-- 用id属性来映射主键字段 -->
		<id column="id" property="id" />
		<!-- 用result属性来映射非主键字段 -->
		<result column="emp_name" property="empName" />
		<result column="age" property="age" />
		
		<discriminator javaType="int" column="age">
			<case value="14" resultType="org.mybatis.pojo.Employee">
				<association property="dept"
						select="org.mybatis.mapper.DepartmentMapper.findDeptById"
						column="d_id">
				</association>
			</case>
			<case value="24" resultType="org.mybatis.pojo.Employee">
				<id column="id" property="id"/>
				<result column="emp_name" property="empName"/>
				<result column="emp_name" property="age"/>
			</case>
		</discriminator>
</resultMap>

猜你喜欢

转载自blog.csdn.net/reallycold/article/details/80175642