本文主要讲述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. LAPM概述及配置

    一.LAMP概述 1.1LAMP的概念 LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态web站点服务及其应用开发环境 LAMP是一个缩写词,具体包括L ...

  2. uniapp/微信小程序 项目day03

    一.商品列表 1.1 获取数据 首先能够进入商品列表的途径 传的数据有 了解了这个之后就可以开始了,先创建分支 创建编译模式,并分配初试数据 这个时候就可以获取数据了 需要的数据 所以在发起请求之前需 ...

  3. .NET 7 AOT 的使用以及 .NET 与 Go 互相调用

    目录 背景 C# 部分 环境要求 创建一个控制台项目 体验 AOT 编译 C# 调用库函数 减少体积 C# 导出函数 C# 调用 C# 生成的 AOT Golang 部分 安装 GCC Golang ...

  4. Git+Github协作开发流程

    采用合作开发者的方式进行协作开发,下面以zlcook和zlserver合作开发iqas-ios-record项目为例进行讲解,zlcook为项目创建者,zlserver为项目参与者.协作开发步骤如下: ...

  5. (GCC) C++代码中使用#pragma GCC optimize / #pragma G++ optimize

    科学计算用优化 经过实验证明这个命令优化效果最好,把我的 1.2S 的 FFT 优化到了 0.4S使用 pragma 命令优化程序: #pragma GCC optimize("Ofast, ...

  6. apt-mirror 制作麒麟桌面版内网源

    apt-mirror 制作麒麟桌面版内网源 一.修改apt软件安装源 1.修改source.list安装源 vi /etc/apt/sources.list 添加: deb http://archiv ...

  7. xamarin.Android自动升级

    在写这边文章的时候参考了很多其他人的博客,在此感谢各位.也是给其他的伙伴做一个总结.对于我们新手来说存在的问题还是比较多的. 一.搭建iis服务器 首先我们需要搭建一个可以提供app下载最新版本的网站 ...

  8. C++使用ODBC连接数据库遇到的问题

    C++使用ODBC连接数据库遇到的问题 1.SQL语句中包含中文无法正常执行的问题 2.字符与宽字符相互转化的问题 C++使用ODBC连接数据库遇到的问题 1.SQL语句中包含中文无法正常执行的问题 ...

  9. 【每日一题】【位于index后的双指针&排序数组】15. 三数之和/NC54 数组中相加和为0的三元组-211117/220206

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组. 注意:答案中不可以包含重复的三 ...

  10. 分布式日志:Exceptionless的安装与部署

    安装步骤 首先exceptionless依赖elasticsearch,而elasticsearch需要java环境,所以先安装jdk jdk下载地址:https://www.oracle.com/t ...