MyBatis的使用七(处理表与表之间的关系)
本文主要讲述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的使用七(处理表与表之间的关系)的更多相关文章
- 使用Mybatis Generator 生产 AS400中的数据表对象
第一次使用Mybatis,由于公司核心服务器是AS400,参考了网络各个大大的教程后,发现无法使用Mybatis Generator自动生成AS400中的表对象 参考URL: http://www.c ...
- MyBatis映射文件的resultMap如何做表关联
MyBatis的核心是其映射文件,SqlMap文件,里面配置了项目中用到了什么SQL语句,和数据库相关的逻辑都在这个映射文件里.顾名思义,映射文件就是对Java对象和SQL的映射.这里简单介绍一下映射 ...
- PE格式第七讲,重定位表
PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...
- MyBatis学习总结(三)——多表关联查询与动态SQL
在上一章中我们学习了<MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射>,这一章主要是介绍一对一关联查询.一对多关联查询与动态SQL等内容. 一.多表关联查询 表与 ...
- mybatis学习(五)----实现关联表查询
一.一对一的表查询 查询班级表中班级号为1的对应的记录(包括教师的具体信息) 1.首先建立数据表 数据表class和techear,class表中只有一个外键techear_id,sql脚本如下: C ...
- 菜鸟nginx源代码剖析数据结构篇(七) 哈希表 ngx_hash_t(下)
菜鸟nginx源代码剖析数据结构篇(七) 哈希表 ngx_hash_t(下) Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:B ...
- 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表
利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...
- MyBatis学习存档(5)——联表查询
之前的数据库操作都是基于一张表进行操作的,若一次查询涉及到多张表,那该如何进行操作呢? 首先明确联表查询的几个关系,大体可以分为一对一和一对多这两种情况,接下来对这两种情况进行分析: 一.建立表.添加 ...
- 菜鸟nginx源码剖析数据结构篇(七) 哈希表 ngx_hash_t(下)[转]
菜鸟nginx源码剖析数据结构篇(七) 哈希表 ngx_hash_t(下) Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.c ...
- Spring Boot入门系列(十七)整合Mybatis,创建自定义mapper 实现多表关联查询!
之前讲了Springboot整合Mybatis,介绍了如何自动生成pojo实体类.mapper类和对应的mapper.xml 文件,并实现最基本的增删改查功能.mybatis 插件自动生成的mappe ...
随机推荐
- 小菜鸡的学习笔记---<正则表达式(1)>
正则表达式学习笔记(1) (纯新手学习笔记,大佬绕路 QAQ) 一.简介 正则表达式就是一种文本模式用来匹配一系列满足特定条件的字符串,可以对比一下数学里面的表达式,比如我们要用一个表达式表示一串数字 ...
- SpringMVC&Maven进阶
3. SpringMVC 3.1 了解SpringMVC 概述 SpringMVC技术与Servlet技术功能等同,均属于web层开发技术 学习路线 请求与响应 REST分割 SSM整合 拦截器 目标 ...
- java反序列化cc_link_one2
CC-LINK-one_second 前言 这条链子其实是上一条链子的另一种走法,在调用危险函数哪里是没有什么变化的 整体链子 还是尾部没有变化嘛还是InvokerTransformer的transf ...
- java学习之爬虫
0x00前言 对比与Python的爬虫机制和java的爬虫机制来详解一下java的爬虫,对于一般性的需求无论java还是python都可以胜任. 如需要模拟登陆.对抗防采集选择python更方便些,如 ...
- mindxdl--common--log_record.go
// Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.// Package common define co ...
- DHorse系列文章之镜像制作
DHorse系列文章之镜像制作 制作镜像常用的工具 使用Docker制作镜像 1.使用docker commit制作 该命令使用比较简单,可以自行网上搜索教程. 2.使用Dockerfile制作 这种 ...
- 硬核!Apache Hudi Schema演变深度分析与应用
1.场景需求 在医疗场景下,涉及到的业务库有几十个,可能有上万张表要做实时入湖,其中还有某些库的表结构修改操作是通过业务人员在网页手工实现,自由度较高,导致整体上存在非常多的新增列,删除列,改列名的情 ...
- Training: MySQL I
原题链接:http://www.wechall.net/challenge/training/mysql/auth_bypass1/index.php 题目告诉我们这是一个经典的mysql注入挑战,我 ...
- 修改msi文件
前言 msi文件是一个安装包文件,可以看做一个数据库,其中包含很多资源,例如图片,配置文件,可执行文件exe等等. 我想要把修改过 exe可执行文件提交到msi文件中,那么就需要知道msi文件的构成, ...
- linux配置 python 开发环境sublime text及一些使用心得
前言 一直以来我都使用 sublime text 作为主流开发的 ide ,但其实我开始在我的 linux mint 系统使用 sublime text 配置 python3 的开发环境踩过的坑又何止 ...