本文主要讲述mybatis的处理表与表之间的关系

一. 介绍t_emp和t_dept表

  1. t_emp表结构

  2. t_dept表结构

二. 数据表的关系

  1. 阐明关系

  一个部门可以有多个员工,但是一个员工只能属于一个部门

  2. 实体类pojo的声明

  1) Employee类的声明如下

public class Employee {
private Integer empId;
private String empName;
private Integer age;
private String gender; private Department dept; public Employee() {
} get和set()方法... @Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", dept=" + dept +
'}';
}
}

  由于一个员工只能属于一个部门,因此在Employee中才会有 private Department dept 成员变量。

  2)Department类声明如下

public class Department {
private Integer deptId;
private String deptName; private List<Employee> employees; public Department() {
} get和set()方法... @Override
public String toString() {
return "Department{" +
"deptId=" + deptId +
", deptName='" + deptName + '\'' +
", employees=" + employees +
'}';
}
}

  由于一个部门可以有多个员工,因此在Department类中才会有 private List<Employee> employees 成员变量

三. 使用mybatis解决多对一【一对多】

  1. 多对一的关系

  这里的多对一的关系是指:多个员工在一个部门,思考的角度是站在员工Employee类的。

  1)提出问题:

  当需要查询单个员工信息以及所在部门时,应该如何处理?

  EmpMapper接口声明如下

public interface EmpMapper {
// 根据id查询员工信息
Employee selectEmpAndDept(@Param("id") int id);
}

  2)处理方式:

  方式1:采用级联的方式

  EmpMapper.xml文件声明如下

    <!--// 根据id查询员工信息
Employee selectEmpAndDept(@Param("id") int id);-->
<!--使用: resultType="Employee"结果: Employee{empId=4, empName='赵六', age=24, gender='男', dept=null}-->
<!--级联-->
<resultMap id="resultEmpAndDept1" type="Employee">
<id column="emp_id" property="empId" />
<result column="emp_name" property="empName" />
<result column="dept_id" property="dept.deptId" />
<result column="dept_name" property="dept.deptName" />
</resultMap>
    <select id="selectEmpAndDept" resultMap="resultEmpAndDept1">
SELECT t_emp.*,t_dept.`dept_name`
FROM t_emp,t_dept
WHERE t_emp.dept_id = t_dept.dept_id and emp_id = #{id}
</select>

  前面提过resultMap可以自定义映射名,下面阐述<resultMap>标签

    <!--
resultMap:
id:resultMap标签的唯一标识
type:返回类型
<id>:表t_emp的主键的字段名
<result>:表t_emp的非主键的字段名
其中
<result column="dept_id" property="dept.deptId" />
column:字段名dept_id,property:实体类的属性名dept.deptId
意义是将查询到的部门信息--封装--》Department对象 --赋值--》Employee类中的dept成员变量
-->
<resultMap id="resultEmpAndDept1" type="Employee">
<id column="emp_id" property="empId" />
<result column="emp_name" property="empName" />
<result column="dept_id" property="dept.deptId" />
<result column="dept_name" property="dept.deptName" />
</resultMap>

  注意:<result column="dept_id" property="dept.deptId" />,是Employee类的成员对象dept . 属性名

  方式2:采用 association 标签

  EmpMapper.xml文件声明如下

    <resultMap id="resultEmpAndDept2" type="Employee">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--association的
property:是需要处理映射关系的属性名,如dept
javaType:是设置要处理属性的类型名称-->
<association property="dept" javaType="Department">
<id column="dept_id" property="deptId"></id>
<id column="dept_name" property="deptName"></id>
</association>
</resultMap>
<select id="selectEmpAndDept" resultMap="resultEmpAndDept2">
SELECT t_emp.*,t_dept.`dept_name`
FROM t_emp,t_dept
WHERE t_emp.dept_id = t_dept.dept_id and emp_id = #{id}
</select>

  下面阐述<association>标签 的内容

   <!--association的
property:是需要处理映射关系的属性名,如dept
javaType:是设置要处理属性的类型名称-->
<association property="dept" javaType="Department">
<id column="dept_id" property="deptId"></id>
<id column="dept_name" property="deptName"></id>
</association>

  方式3:采用分步查询

  先根据员工编号,查询员工信息,在根据员工信息中的部门编号,查询相对应的部门信息

  因此,需要创建DeptMapper接口,DeptMapper接口的声明如下

public interface DeptMapper {

    // 根据id查询部门
Department selectDeptById(@Param("id") int id);
}

  DeptMapper.xml文件声明如下

<!--namespace绑定mapper的接口所在的包名.接口名-->
<mapper namespace="com.hspedu.mapper.DeptMapper">
<!--// 根据id查询部门
Department selectDeptById(@Param("id") int id);-->
<select id="selectDeptById" resultType="Department">
select * from t_dept where dept_id = #{id}
</select> </mapper>

  EmpMapper.xml文件声明如下

  <resultMap id="resultEmpAndDept3" type="Employee">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--association的
property:设置需要处理映射关系的属性的属性名
select:设置分步查询的sql语句的唯一标识
column:将select标签中查询出的某一个字段作为分步查询的条件
fetchType:是否开启延迟加载【针对某一个sql语句】eager立刻,lazy延迟
-->
<association property="dept" fetchType="eager"
select="com.hspedu.mapper.DeptMapper.selectDeptById"
column="dept_id">
</association>
</resultMap>
<select id="selectEmpAndDeptThree" resultMap="resultEmpAndDept3" >
select * from t_emp where emp_id = #{id}
</select>

  下面阐述 <association> 标签的内容

   <!--association的
property:设置需要处理映射关系的属性的属性名
select:设置分步查询的sql语句的唯一标识
column:将select标签中查询出的某一个字段作为分步查询的条件
fetchType:在方法中是否开启延迟加载【针对某一个sql语句】eager立刻,lazy延迟
-->
<association property="dept" fetchType="eager"
select="com.hspedu.mapper.DeptMapper.selectDeptById"
column="dept_id">
</association>

  注意:association标签中的select的意义,

  在t_emp表中查询到的员工信息字段中的dept_id值作为参数,传入到DeptMapper接口的selectDeptById()方法中,

  在t_dept表中按照部门编号dept_id查询相对应的部门信息。

  分步查询 插入一个知识点:延迟加载

  a> 引入延迟加载

    当我们只是想查询员工信息的姓名时,例如

    @Test
// 查询指定id的员工信息
public void test02(){
Employee employee = mapper.selectEmpAndDept(4);
System.out.println(employee.getEmpName());
}

    如果没有延迟加载的话,执行结果如下

DEBUG 02-04 15:37:05,646 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-04 15:37:05,669 ====> Preparing: select * from t_dept where dept_id = ? (BaseJdbcLogger.java:137)
DEBUG 02-04 15:37:05,669 ====> Parameters: 100(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-04 15:37:05,675 <==== Total: 1 (BaseJdbcLogger.java:137)
DEBUG 02-04 15:37:05,677 <== Total: 1 (BaseJdbcLogger.java:137)
赵六

    即执行了查询员工信息的sql语句,又执行了查询部门信息的sql语句,如何让它不执行查询部门信息的sql语句呢?

  b> 延迟加载的配置

    在mybatis-config.xml文件中添加如下setting标签,引入延迟加载

    <settings>
<!--将MySQL中_映射为java的驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延时加载【懒加载】-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--强制加载所有的懒配置-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

    并将<association fetchType="eager"> 的  fetchType = "lazy",即在执行该sql语句时,使用延迟加载,执行结果如下

DEBUG 02-04 15:42:26,231 ==>  Preparing: select * from t_emp where emp_id = ? (BaseJdbcLogger.java:137)
DEBUG 02-04 15:42:26,261 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-04 15:42:26,322 <== Total: 1 (BaseJdbcLogger.java:137)
赵六

    只执行了查询员工信息的sql语句,说明延迟加载有了效果。

   c> 延迟加载总结:

    引入延迟加载,在mybatis配置文件中添加setting标签......【全局 延迟加载】

    如果对于某一个sql语句,不想使用延迟加载,则<association fetchType="eager"> 【局部 不使用延迟加载】

  3)总结:

  根据传入的emp_id在t_emp表中查询员工信息,员工信息的字段中包含有dept_id,然后依据dept_id,在t_dept表中查询相应的部门信息,

  将部门信息--反射-->Department类的对象--赋值-->Employee类的成员变量dept。

  2. 一对多关系

  这里的一对多是一个部门可以有多个员工,是在Department类角度考虑的。

  1)提出问题

  按照部门编号查询一个部门有多少员工?

  DeptMapper接口声明如下

public interface DeptMapper {

    // 查询一个部门有多少员工
Department selectDeptAndEmp(@Param("id") int id);
}

  2)处理方式

  方式1:使用collection标签

  DeptMapper.xml文件声明如下

    <!--// 查询一个部门有多少员工
Department selectDeptAndEmp(@Param("id") int id);-->
<resultMap id="resultDeptAndEmp1" type="Department">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="employees" ofType="Employee">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age" ></result>
<result column="gender" property="gender"></result>
</collection>
</resultMap>
<select id="selectDeptAndEmp" resultMap="resultDeptAndEmp1">
SELECT t_emp.*,t_dept.*
FROM t_emp,t_dept
WHERE t_emp.`dept_id` = t_dept.`dept_id` and t_dept.dept_id = #{id}
</select>

  下面阐述collection标签

    <collection property="employees" ofType="Employee">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age" ></result>
<result column="gender" property="gender"></result>
</collection>

  property:实体类的成员变量【属性】,ofType:表示将查询的结果--封装-->实体类对象--装入-->集合

  方式2:分步查询

  第一步:在t_dept表中根据传入的dept_id查询部门信息

  第二步:在t_emp中根据第一步中得到的dept_id查询员工信息

  EmpMapper接口的声明如下

public interface EmpMapper {

    // 根据部门编号查询员工信息
List<Employee> selectEmployeesByDeptId(@Param("id") int id);
}

  EmpMapper.xml文件声明如下

    <!-- // 根据部门编号查询员工信息
List<Employee> selectEmployeesByDeptId(@Param("id") int id);-->
<resultMap id="resultEmployeesByDeptId" type="Employee">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
</resultMap>
<select id="selectEmployeesByDeptId" resultMap="resultEmployeesByDeptId">
select * from t_emp where dept_id = #{id}
</select>

  DeptMapper.xml文件声明如下

     <resultMap id="resultDeptAndEmp" type="Department">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<association property="employees" fetchType="lazy"
select="com.hspedu.mapper.EmpMapper.selectEmployeesByDeptId"
column="dept_id"></association>
</resultMap>
<select id="selectDeptAndEmpTwo" resultMap="resultDeptAndEmp">
select * from t_dept where dept_id = #{id}
</select>

  使用association标签,

  property:实体类需要映射处理的成员名【属性】;

  select:调用EmpMapper接口的 selectEmployeesByDeptId()方法,即 根据得到的部门信息中的dept_id,在t_emp表中查询该部门的所有员工信息。

  3)总结

  由dept_id在t_emp查询的结果集--反射-->Employee对象--装入-->Employee集合--赋值-->Department类的employees成员变量。

  

  

MyBatis的使用七(处理表与表之间的关系)的更多相关文章

  1. 使用Mybatis Generator 生产 AS400中的数据表对象

    第一次使用Mybatis,由于公司核心服务器是AS400,参考了网络各个大大的教程后,发现无法使用Mybatis Generator自动生成AS400中的表对象 参考URL: http://www.c ...

  2. MyBatis映射文件的resultMap如何做表关联

    MyBatis的核心是其映射文件,SqlMap文件,里面配置了项目中用到了什么SQL语句,和数据库相关的逻辑都在这个映射文件里.顾名思义,映射文件就是对Java对象和SQL的映射.这里简单介绍一下映射 ...

  3. PE格式第七讲,重定位表

    PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...

  4. MyBatis学习总结(三)——多表关联查询与动态SQL

    在上一章中我们学习了<MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射>,这一章主要是介绍一对一关联查询.一对多关联查询与动态SQL等内容. 一.多表关联查询 表与 ...

  5. mybatis学习(五)----实现关联表查询

    一.一对一的表查询 查询班级表中班级号为1的对应的记录(包括教师的具体信息) 1.首先建立数据表 数据表class和techear,class表中只有一个外键techear_id,sql脚本如下: C ...

  6. 菜鸟nginx源代码剖析数据结构篇(七) 哈希表 ngx_hash_t(下)

      菜鸟nginx源代码剖析数据结构篇(七) 哈希表 ngx_hash_t(下)   Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:B ...

  7. 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表

    利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...

  8. MyBatis学习存档(5)——联表查询

    之前的数据库操作都是基于一张表进行操作的,若一次查询涉及到多张表,那该如何进行操作呢? 首先明确联表查询的几个关系,大体可以分为一对一和一对多这两种情况,接下来对这两种情况进行分析: 一.建立表.添加 ...

  9. 菜鸟nginx源码剖析数据结构篇(七) 哈希表 ngx_hash_t(下)[转]

    菜鸟nginx源码剖析数据结构篇(七) 哈希表 ngx_hash_t(下) Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.c ...

  10. Spring Boot入门系列(十七)整合Mybatis,创建自定义mapper 实现多表关联查询!

    之前讲了Springboot整合Mybatis,介绍了如何自动生成pojo实体类.mapper类和对应的mapper.xml 文件,并实现最基本的增删改查功能.mybatis 插件自动生成的mappe ...

随机推荐

  1. 抓包分析 TCP 握手和挥手

    前言 首先需要明确的是 TCP 是一个可靠传输协议,它的所有特点最终都是为了这个可靠传输服务.在网上看到过很多文章讲 TCP 连接的三次握手和断开连接的四次挥手,但是都太过于理论,看完感觉总是似懂非懂 ...

  2. springboot集成支付宝的支付(easy版)

    SpringBoot对接支付宝 需要先注册账号 到支付宝开发者平台创建网页支付应用 启用公钥模式 需要使用到appId和下面的两个秘钥 写配置信息的代码 1.引入依赖 <dependency&g ...

  3. 题解合集 (update on 11.5)

    收录已发布的题解 按发布时间排序. 部分可能与我的其他文章有重复捏 qwq . AtCoder for Chinese: Link ZHOJ: Link 洛谷 \(1\sim 5\) : [题解]CF ...

  4. mybatis实现数据行级权限拦截

    最近在做一个测试平台,其中有一个需求是用户只能看到他有权限的项目数据.一开始这个需求只针对用例模块,我直接在sql后面加上了关联项目权限表.后面因为其他模块也需要这个权限判断,故打算把关联sql抽取出 ...

  5. PGL图学习之图神经网络GraphSAGE、GIN图采样算法[系列七]

    0. PGL图学习之图神经网络GraphSAGE.GIN图采样算法[系列七] 本项目链接:https://aistudio.baidu.com/aistudio/projectdetail/50619 ...

  6. netty系列之:在netty中使用proxy protocol

    目录 简介 netty对proxy protocol协议的支持 HAProxyMessage的编码解码器 netty中proxy protocol的代码示例 总结 简介 我们知道proxy proto ...

  7. python进阶(28)import导入机制原理

    前言 在Python中,一个.py文件代表一个Module.在Module中可以是任何的符合Python文件格式的Python脚本.了解Module导入机制大有用处. 1. Module组成 一个.p ...

  8. 关于led蓝牙控制器ble通信分析

    前言 前几天在网上买了一个led蓝牙控制器,可以用手机app通过蓝牙连接控制rgb led灯,当然这个也是属于ble通信.之前我写过一篇体重称蓝牙通信的,不过那个较为简单,数据也是靠分析出来的. 这次 ...

  9. 关于linux mint更改资源管理器的快捷键

    前言 首先要知道 linux mint 的默认资源管理器是 nemo 我很不习惯 ctrl+d 在nemo里面是 收藏到侧边栏 我习惯 ctrl+d 在windows上是删除文件 所以下面我就修改这个 ...

  10. 07#Web 实战:实现 GitHub 个人主页项目拖拽排序

    实现效果图 GitHub 和 Gitee 个人主页中可以对自己的项目进行拖拽排序,于是我就想自己实现一个.本随笔只是记录一下大概的实现思路,如果感兴趣的小伙伴可以通过代码和本随笔的说明去理解实现过程. ...