一、myBatis对象关系映射(多对一关系、一对多关系)

1、多对一关系:

---例子:多个员工同属于一个部门。


(1)myBatis发送 额外SQL:

■ 案例:员工表通过 dept_id 关联 部门表,需求:查询指定员工id、name、所属的部门名称的信息。

//部门对象的接口、映射文件省略,跟员工逻辑差不多

/* 员工对象的接口 */
public interface EmployeeMapper {
Employee get(Long id);
} <!--员工对象的映射文件-->
<!-- 解决列名和属性名不匹配问题 -->
<resultMap id="BaseResultMap" type="Employee">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="dept_id" property="dept.id"/>
</resultMap> <!-- 查询操作 -->
<select id="get" resultMap="BaseResultMap">
select id, name, dept_id from employee2 where id = #{id}
</select> /* 测试:查询指定员工id、name、所属的部门名称的信息 */
@Test
public void testGet() throws Exception {
SqlSession session = MyBatisUtil.getSession();
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee e = employeeMapper.get(1L);
System.out.println(e);
//需要通过查询得到的dept_id查询获取得到部门对象
/**
* 额外的查询语句,可以通过配置resultMap的association属性,让myBatis帮我们执行
*/
//手动添加额外查询语句
// Long dept_id = e.getDept().getId();
// DepartmentMapper departmentMapper = session.getMapper(DepartmentMapper.class);
// Department d = departmentMapper.get(dept_id);
// e.setDept(d); System.out.println(e.getDept());
session.commit();
session.close();
}
  • 上面是通过手动添加的额外SQL查询,通过配置resultMap的association属性,让myBatis帮我们执行如下:

	<!-- 解决列名和属性名不匹配问题 -->
<resultMap id="BaseResultMap" type="Employee">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--<result column="dept_id" property="dept.id"/> -->
<!-- 额外的SQL配置方式
association元素:配置单一元素的关联关系
property 属性:对象的属性
select 属性:发送额外的sql
column 属性: 将指定的列的值传递给额外sql
-->
<association property="dept"
select="com.shan.hello.mappe r.DepartmentMapper.get"
column="dept_id"
/> </resultMap>

(2)使用额外的 SQL 做映射配置会导致的问题:N+1问题

例如:每个员工的部门编号dept_id 是不同的,当查询所有员工的id、name、所属的部门名称的信息时就会发送额外N条SQL语句。

  • N:发送额外N条SQL语句去查询员工所属的部门名称: select name from department where id = dept_id;

  • 1:查询所有员工的id、name、所属的部门的编号dept_id:select * from employee;

----解决:使用内联映射(多表查询),此时一条 SQL 语句搞定。

----处理多表查询的结果集的方法:内联映射

(3)对象关联的查询:

方式一:额外的SQL

方式二:内联映射

(4)处理多表查询的结果集的方法【内联映射】:

  • 方式一:属性名-列名 通过resultMap的子元素result进行映射配置[内联映射-使用result]:

  • 方式二:属性名-列名 通过resultMap的子元素association进行映射配置[内联映射-使用association]

(5)多对一关系配置总结:

使用association元素,配置单一对象属性。

  • 方式一:额外的SQL[分步查询],一般需要进入另外一个页面展示更加详细的信息。
  • 方式二:内联映射[多表查询],常用。需要在列表中显示关联对象的数据,使用内联映射,否则会出现N+1问题。

2、一对多关系配置:

---例子:一个部门有多个员工。


(1)一对多关系-额外的SQL:

<!-- 针对单一对象的属性,使用association元素 -->
<!-- 针对集合类型的属性,使用collection元素 -->
<!-- 额外的SQL配置方式
collection元素:配置集合类型元素的关联关系
property 属性:对象的属性
select 属性:发送额外的sql
column 属性: 将指定的列的值传递给额外sql
--> <resultMap id="BaseResultMap" type="Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--<result column="" property="emps"/> -->
<collection property="emps"
select="com.shan.hello.mapper.EmployeeMapper.get"
column="id" >
</collection>
</resultMap> <select id="get" resultMap="BaseResultMap">
select id, name from department where id = #{id}
</select>

(2)一对多关系-内联查询:

<!-- 针对单一对象的属性,使用association元素 -->
<!-- 针对集合类型的属性,使用collection元素 -->
<resultMap id="BaseResultMap" type="Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--<result column="" property="emps"/> -->
<!--
内联查询:ofType是集合中泛型的类型
-->
<collection property="emps" ofType="Employee">
<result column="e_id" property="id"/>
<result column="e_name" property="name"/>
<result column="e_dept_id" property="deptId"/>
</collection>
</resultMap> <select id="get" resultMap="BaseResultMap">
<!-- select id, name from department where id = #{id} -->
select d.id, d.name, e.id e_id, e.name e_name, e.dept_id e_dept_id from department d
join employee2 e on d.id = e.dept_id where d.id = #{id}
</select>

二、设置延迟/懒加载

  	<!-- 全局配置文件 -->
<settings>
<!-- 懒加载/延迟加载,开启延迟加载功能 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置不要积极地去查询关联对象 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 延迟加载的触发方法 -->
<setting name="lazyLoadTriggerMethods" value="close"/>
</settings>
  • 动态代理-增强功能--延迟加载

总结:多对一、一对多关系的单属性对象/集合属性对象,使用association或collection元素?使用额外SQL或内联查询?

  • 针对【单属性对象】:使用assoication元素,通常需要使用多表查询操作,即内联查询

  • 针对【集合属性对象】:使用collection元素,通常还要使用延迟加载,即额外SQL处理

MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载的更多相关文章

  1. 019 关联映射文件中集合标签中的lazy(懒加载)属性

    <set>.<list>集合上,可以取值:true/false/extra,(默认值为:true) 实例一:(集合上的lazy=true(默认))class默认lazy=tru ...

  2. 018 关联映射文件中<class>标签中的lazy(懒加载)属性

    Lazy(懒加载): 只有在正真使用该对象时,才会创建这个对象 Hibernate中的lazy(懒加载): 只有我们在正真使用时,它才会发出SQL语句,给我们去查询,如果不使用对象则不会发SQL语句进 ...

  3. hibernate学习五(关系映射多对一与一对多)

    一.多对一 多对一(或者一对多):在学生与老师的情况下,一个老师可以教多个学生,但一个学生只能被教一个老师教: 对于类:在多的那方拥有一的那方的一个实体 二.修改student.java和teache ...

  4. mybatis(三)懒加载

    懒加载的好处: 所谓懒加载(lazy)就是延时加载,延迟加载.什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载.至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,因为 ...

  5. 关于 Mybatis 设置懒加载无效的问题

    看了 mybatis 的教程,讲到关于mybatis 的懒加载的设置: 只需要在 mybatis 的配置文件中设置两个属性就可以了: <settings> <!-- 打开延迟加载的开 ...

  6. MyBatis --- 映射关系【一对一、一对多、多对多】,懒加载机制

    映射(多.一)对一的关联关系 1)若只想得到关联对象的id属性,不用关联数据表 2)若希望得到关联对象的其他属性,要关联其数据表 举例: 员工与部门的映射关系为:多对一 1.创建表 员工表 确定其外键 ...

  7. Mybatis学习(四)————— 高级映射,一对一,一对多,多对多映射

    一.单向和双向 包括一对一,一对多,多对多这三种情况,但是每一种又分为单向和双向,在hibernate中我们就详细解析过这单向和双向是啥意思,在这里,在重复一遍,就拿一对多这种关系来讲,比如有员工和部 ...

  8. Spring Data JPA 关系映射(一对一,一对多,多对多 )

    CascadeType.REMOVE 级联删除操作,删除当前实体时,与它有映射关系的实体也会跟着被删除.CascadeType.MERGE 级联更新(合并)操作,当Student中的数据改变,会相应地 ...

  9. mybatis 详解(八)------ 懒加载

    本章我们讲如何通过懒加载来提高mybatis的查询效率. 本章所有代码:http://pan.baidu.com/s/1o8p2Drs 密码:trd6 1.需求:查询订单信息,有时候需要关联查出用户信 ...

随机推荐

  1. 「算法笔记」状压 DP

    一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...

  2. JWT+SpringBoot实战

    往期内容:JWT - 炒焖煎糖板栗 - 博客园 (cnblogs.com) JWT可以理解为一个加密的字符串,里面由三部分组成:头部(Header).负载(Payload).签名(signature) ...

  3. CS5216 设计于DP转HDMI转换器|DP转HDMI 1080P中继器 电平转化器开关设计方案与线路图

    CS5216是一款Displayport to hdmi 1080p音视频信号转换芯片,主要用于设计与开发DP转HDMI 转换器.中继器.电平转换器等产品当中.它支持交流和直流耦合TMDS信号高达1. ...

  4. Java面向对象笔记 • 【第7章 集合】

    全部章节   >>>> 本章目录 7.1 集合概述 7.1.1 Java集合体系概述 7.1.2 实践练习 7.2 List集合 7.2.1 ArrayList实现类 7.2. ...

  5. Windows下安装配置jdk

    1.jdk安装 从官网获取jdk安装包后, 双击图形化安装,一路next即可. 2.配置JavaHome 打开计算机->系统属性->高级系统设置->环境变量 在系统变量下面添JAVA ...

  6. 深入 Laravel 内核之装饰模式

    装饰模式核心内容: 装饰模式可以在不影响组件对象的情况下,以动态.透明的方式从外部给对象添加功能: 装饰器模式的本质就是动态组合.动态是手段,组合是目的.装饰模式是通过把复杂的功能简单化.分散化,在运 ...

  7. shell3-循环

    常用的循环语句有3种: <1>for <2>while <3>utile 1.for语句的格式: for 变量名 in 列表: do 循环体 done 如何生成列表 ...

  8. 官网下载mysql的方法

    mysql官网    http://www.mysql.com/ 方法一:    (1)登陆官网 (2)把页面拉到最底部,点击Downloads(GA) 下边的MySQL Community Serv ...

  9. STM32时钟系统的配置寄存器和源码分析

    一.时钟系统 概述 时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令,时钟系统就是CPU的脉搏,决定cpu速率. STM32有多个时钟来源的选择,为什么 STM32 要有多个时钟源呢 ...

  10. pip list 精确查找某一模块的方法

    1. 今天搜资料的时候get一项技能: pip list精确查找某一模块 命令如下: pip list | findstr "win32" (此处win32可以替换成任意想查找的模 ...