Mybatis 的关联映射(一对一,一对多,多对多)

前言

  在前面我们已经了解了,mybatis 的基本用法,动态SQL,学会使用mybatis 来操作数据库。但这些主要操作还是针对 单表实现的。在实际的开发中,对数据库的操作,常常涉及多张表。

因此本篇博客的目标:通过mybatis 提供的关联映射,建立表与表之间的关系,实现多表的数据操作。


关联映射的概述

在关系型数据库中,表与表之间存在3 种关联映射关系,分别是 一对一,一对多/多对一,和多对多

1. 一对一(One-to-One)

一对一关系是指一个表中的每个记录与另一个表中的一个记录相关联,且这种关联是唯一的。例如:

  • 一个学生只能有一个学生证,一个学生证只属于一个学生。

  • 一个用户只能有一个个人资料,一个个人资料只属于一个用户。

在数据库设计中,一对一关系可以通过以下方式实现:

  • 主键关联:将一个表的主键作为外键放在另一个表中。

  • 联合主键:将两个表的主键合并为一个联合主键,存储在一张表中。

2. 一对多/多对一(One-to-Many/Many-to-One)

一对多关系是指一个表中的一个记录可以与另一个表中的多个记录相关联,而另一个表中的每个记录只能与第一个表中的一个记录相关联。例如:

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

  • 一个作者可以写多本书,但每本书只能由一个作者创作。

在数据库设计中,一对多关系通常通过外键来实现:

  • 在“多”的一方的表中添加一个外键字段,指向“一”的一方的主键字段。

3. 多对多(Many-to-Many)

多对多关系是指一个表中的多个记录可以与另一个表中的多个记录相关联。例如:

  • 一个学生可以选修多门课程,一门课程也可以被多个学生选修。

  • 一个作者可以写多本书,一本书也可以由多个作者共同创作。

注意

在数据库设计中,多对多关系通常通过一个**关联表(中间表)**来实现:

  • 关联表包含两个表的主键作为外键字段,用于建立多对多关系。

  • 例如,对于学生和课程的多对多关系,可以创建一个选课表,包含学生ID和课程ID作为外键字段。


一对一查询

应用场景

例如  表示 一个人 只能有一个身份证,同时一个身份证也只对应一个人

重点

在学习 一对一查询 时,核心是学习使用 <association>元素 来处理 一对 对关联关系。 <association>元素 提供了一系列 属性用于维护数据表之间的关系

<association>元素 常用的属性

属性说明
property用于指定映射到的实体类的属性,与表字段一一对应
Column用于指定表中的对应的字段
javaType用于指定映射到实体对象的属性
jdbcType用于指定数据表中对应的字段类型
fetchType用于指定在关联查询时是否启用延迟加载。fetchType属性 有lazy,eager两个属性值,默认为lazy(默认关联映射延迟加载)
select用于指定引入嵌套查询的子SQL语句,该属性用于关联映射的前提查询
autoMapper用于指定是否自动映射
typeHander用于指定一个类型处理器

<association>元素 是<resultMap>元素的子元素,它有两种配置方式 :嵌套查询方式,嵌套结果方式

嵌套查询方式,嵌套结果方式的区别

我理解 嵌套查询方式是多步走,而不是一步到位。例如 你写一个 复合sql语句【相当于sql 嵌套着其他的sql 语句】,去查表中的数据,现在是把这个sql 语句拆开,通过表之间的关系 ,一个个去查,最好得到结果。

样例

<!--        嵌套查询方式--><association property="card" column="card_id" javaType="fs.pojo.IdCard" select="fs.mapper.IdCardMapper.findCodeById"/>

嵌套结果方式,则是一步到位。通过使用一个复合的sql 语句【相当于sql 嵌套着其他的sql 语句】得到最终结果。

样例

<!--        嵌套结果查询--><association property="card" javaType="fs.pojo.IdCard" ><id property="id" column="card_id"/><result property="code" column="CODE"/></association>

demo(案例)

项目准备

数据库中 tb_person 表,tb_idcard 表

实体类 IdCard 类,Person 类

mybatis -config 配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties"></properties>  <settings><!--    environment 是一个环境,里面包含一个事务管理器,一个数据源 --><environments default="development"><environment id="development"><transactionManager type="JDBC"></transactionManager><dataSource type="POOLED"><!-- 配置数据源信息,主要有 数据库驱动,数据库连接地址,数据库用户名,数据库密码等               --><property name="driver" value="${driverClass}"></property><property name="url" value="${jdbcUrl}"></property><property name="username" value="${username}"></property><property name="password" value="${password}"></property></dataSource></environment></environments><mappers><!-- 使用mapper 标签 指定mapper映射文件--><mapper resource="mapper/PersonMapper.xml"/><mapper resource="mapper/IdCardMapper.xml"/><mapper resource="mapper/UserMapper.xml"/><mapper resource="mapper/OrdersMapper.xml"/><mapper resource="mapper/ProductMapper.xml"/></mappers>
</configuration>

问题:当输入 id=1时,查询person 人的具体信息包括个人身份证信息

PersonMapper 接口

 // 根据id查询Person findPersonById(Integer id);Person findPersonById2(Integer id);

PersonMapper.xml 映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="fs.mapper.PersonMapper">
// 需要针对 数据库做的操作【查询,修改,删除,插入】
</mapper>

 嵌套查询方式【多步到位】

<select id="findPersonById" parameterType="int" resultMap="card">select * from tb_person where id = #{id}
</select><resultMap id="card" type="fs.pojo.Person"><id property="id" column="id"/><result property="name" column="name"/><result property="sex" column="sex"/><result property="age" column="age"/>
<!--        嵌套查询方式--><association property="card" column="card_id" javaType="fs.pojo.IdCard"select="fs.mapper.IdCardMapper.findCodeById"/></resultMap>
 嵌套查询方式 接口的findCodeById 方法和IdCardMapper.xml映射文件
  • 接口的findCodeById 方法

  • IdCardMapper.xml映射文件

嵌套结果方式【一步到位】

   <select id="findPersonById2" parameterType="int" resultMap="card2">select p.*, c.code from tb_person p , tb_idcard c where p.id = #{id} and p.card_id = c.id</select><resultMap id="card2" type="fs.pojo.Person"><id property="id" column="id"/><result property="name" column="name"/><result property="sex" column="sex"/><result property="age" column="age"/>
<!--        嵌套结果查询--><association property="card" javaType="fs.pojo.IdCard" ><id property="id" column="card_id"/><result property="code" column="CODE"/></association></resultMap>

一对多查询

应用场景

与一对一的关联相比,更多关联关系是一对多(或多对一)例如 一个用户 可以有多个订单,多个订单也可以归一个用户所有。

重点使用<collection>元素来处理一对多关联关系。

<collection>元素 和<association>元素的关系

1 <collection>元素 的属性 大部分与 <association> 元素 相同,但其还包含一个特殊属性--ofType

ofType 与javaType属性相对应,用于指定实体类对象中集合类属性所包含的元素类型集合中存储的实体类对象类型


2 与 <association> 元素 相同 ,也是<resultMap>元素的子元素,<collection> 元素 也嵌套查询和嵌套结果两者配置方式

demo(案例)

项目准备

数据库 中 tb_user用户表 ,tb_order 订单表

实体类 User 用户 类,Orders订单类

问题:当输入用户 id=1,时获得 该用户所有的订单情况

UserMapper接口

package fs.mapper;import fs.pojo.User;public interface UserMapper {User findUserWithOrders(Integer id);
}

UserMapper.xml 映射文件

  • 嵌套结果查询方式【一步到位】

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="fs.mapper.UserMapper"><select id="findUserWithOrders" parameterType="int" resultMap="orders">select u.*,o.id as orders_id,o.number from tb_user u, tb_orders owhere u.id = o.user_id and u.id = #{id}</select><resultMap id="orders" type="fs.pojo.User"><id property="id" column="id"/><result property="username" column="username"/><result property="address" column="address"/><collection property="orders" ofType="fs.pojo.Orders"><id property="id" column="orders_id"/><result property="number" column="number"/></collection></resultMap>
</mapper>

多对多查询

应用场景

多对多查询 和一对多查询,在现实生活也是非常常见的。以订单和商品为例,一个订单可以包含多种商品,而一种商品又可以属于多种订单中,订单和商品就是典型的多对多的关系。

重点使用<collection>元素来处理多对多关联关系。

demo(案例)

项目准备

数据库中 tb_orders 订单表 ,tb_product 商品表 

中间表 tb_ordersitem

实体类 Product用户 类,Orders订单类

问题:当输入 订单 id=1 时,查询 该订单中所有的商品信息

OrderMapper 接口

package fs.mapper;import fs.pojo.Orders;
public interface OrdersMapper {
Orders  findOrdersWithProduct(Integer id);Orders  findOrdersWithProduct1(Integer id);
}

OrderMapper 映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="fs.mapper.OrdersMapper">
// 各自数据库的操作
</mapper>

嵌套查询方式【多步到位】

 <select id="findOrdersWithProduct1" parameterType="int" resultMap="orders">select * from tb_orders where id=#{id};</select><resultMap id="orders" type="fs.pojo.Orders"><id property="id" column="id"/><result property="number" column="number"/><collection property="productList"  column="id" ofType="fs.pojo.Product" select="fs.mapper.ProductMapper.findProductById"></collection></resultMap>

嵌套查询方式 接口的findProductById 方法和ProductMapper.xml映射文件
  • ProductMapper 接口 

  • ProductMapper.xml 映射文件


嵌套结果方式【一步到位】

  • 没有给 tb_product 表的 id 字段 添加别名为 pid 之前
产生问题

当两者关联的表存在相同的字段时,在执行sql 查询 后,会因为tb_order表的id 字段和tb_product 的 id字段 相同,导致 查询结果在映射到product 实体类对象时,后面的product 对象始终会把前面的product 对象覆盖掉。本来应该查询多个 product对象信息,但最好打印只有 1个【最好一个product对象信息】

运行截图

如果给 tb_product 表的 id 字段 添加别名 或者 给 tb_orders 表 的 id 字段添加别名

  • 在这里我是给 tb_product 表的 id 字段 添加别名 为 pid

运行截图

  • 最好确实出现了3 个product 对象的具体信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/31332.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3通过render函数实现一个菜单下拉框

背景说明 鼠标移动到产品服务上时&#xff0c;出现标红的下拉框。 使用纯css的方案实现最简单&#xff0c;但是没什么技术含量&#xff0c;弃之&#xff1b;使用第三方组件库&#xff0c;样式定制麻烦弃之。因此&#xff0c;我们使用vue3直接在页面创建一个dom作为下拉框吧。…

Docker介绍和安装

跨平台快速运行应用快速构建应用快速分享应用 docker是用来加速,构建,分享,运行的容器 在 Docker 的架构中&#xff0c;Client、Docker Host 和 Registry 是三个核心组成部分&#xff0c;它们各自承担不同的功能和作用。以下是对这三部分的详细描述&#xff1a; Docker的基本…

nnMamba:基于状态空间模型的3D生物医学图像分割、分类和地标检测

摘要 本文提出了一种基于状态空间模型&#xff08;SSMs&#xff09;的创新架构——nnMamba&#xff0c;用于解决3D生物医学图像分割、分类及地标检测任务中的长距离依赖建模难题。nnMamba结合了卷积神经网络&#xff08;CNN&#xff09;的局部特征提取能力与SSMs的全局上下文建…

elasticsearch商业产品

Elasticsearch商业产品介绍 在当今数字化时代&#xff0c;数据如同石油一样珍贵。而要从海量的数据中提取有价值的信息&#xff0c;则需要强大的工具。这就是Elasticsearch商业产品的用武之地。Elasticsearch是一款开源的搜索引擎&#xff0c;它能够快速地存储、搜索和分析大规…

git安装,配置SSH公钥(查看版本、安装路径,更新版本)git常用指令

目录 一、git下载安装 1、下载git 2、安装Git‌&#xff1a; 二、配置SSH公钥 三、查看安装路径、查看版本、更新版本 四、git常用指令 1、仓库初始化与管理 2、配置 3、工作区与暂存区管理 4、提交 5、分支管理 6、远程仓库管理 7、版本控制 8、其他高级操作 一…

c++的基础排序算法

一、快速排序 1. 选择基准值&#xff08;Pivot&#xff09; 作用 &#xff1a;从数组中选择一个元素作为基准&#xff08;Pivot&#xff09;&#xff0c;用于划分数组。常见选择方式 &#xff1a; 固定选择最后一个元素&#xff08;如示例代码&#xff09;。随机选择&#xf…

kali linux 漏洞扫描

Kali Linux是一款专为渗透测试和网络安全领域而设计的操作系统&#xff0c;它集成了大量的安全测试工具&#xff0c;可以帮助安全专家和黑客发现网络中的漏洞并加以修补。在Kali Linux中&#xff0c;漏洞扫描是一个非常重要的功能&#xff0c;它可以帮助用户快速、准确地发现系…

CI/CD—Jenkins配置Maven+GitLab自动构建jar包

一、安装Maven插件通过Maven构建项目 1、在Jenkins上安装Maven Integration plugin插件 2、创建一个maven项目 2.1、填写构建的名称和描述等 2.2、填写连接git的url 报错&#xff1a;无法连接仓库&#xff1a;Error performing git command: git ls-remote -h http://192.168.…

SpringBoot使用Nacos进行application.yml配置管理

Nacos是阿里巴巴开源的一个微服务配置管理和服务发现的解决方案。它提供了动态服务发现、配置管理和 服务管理平台。Nacos的核心功能包括服务发现、配置管理和动态服务管理&#xff0c;使得微服务架构下的服务治理 变得简单高效。 Nacos的设计基于服务注册与发现、配置管理、动…

深度学习分类回归(衣帽数据集)

一、步骤 1 加载数据集fashion_minst 2 搭建class NeuralNetwork模型 3 设置损失函数&#xff0c;优化器 4 编写评估函数 5 编写训练函数 6 开始训练 7 绘制损失&#xff0c;准确率曲线 二、代码 导包&#xff0c;打印版本号&#xff1a; import matplotlib as mpl im…

学习资料电子版 免费下载的网盘网站(非常全!)

我分享一个私人收藏的电子书免费下载的网盘网站&#xff08;学习资料为主&#xff09;&#xff1a; link3.cc/sbook123 所有资料都保存在网盘了&#xff0c;直接转存即可&#xff0c;非常的便利&#xff01; 包括了少儿&#xff0c;小学&#xff0c;初中&#xff0c;中职&am…

解锁 AI 量化新境界:Qbot 携手 iTick

在量化投资的汹涌浪潮中&#xff0c;你是否渴望拥有一个强大且便捷的工具&#xff0c;助你乘风破浪&#xff0c;驶向财富的彼岸&#xff1f;如今&#xff0c;Qbot 与 iTick 强强联合&#xff0c;为广大投资者和开发者打造出一个前所未有的 AI 量化生态系统。 Qbot&#xff1a;量…

前端性能优化

在当今快节奏的互联网环境中&#xff0c;前端性能优化不仅能提升用户体验&#xff0c;还能直接影响网站的SEO排名和用户留存率。那么&#xff0c;如何做好前端性能优化呢&#xff1f; 前端性能优化成为提升用户体验和业务成果的关键。研究显示&#xff0c;优化网页加载速度和运…

谷歌AI最新发布的可微分逻辑元胞自动机(DiffLogic CA)

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

忘记dedecms后台超级管理员账号和密码的解决方案

解决方案&#xff1a; 方案一、数据库修改&#xff1a; 1、前提是您能登录到数据库后台&#xff0c;登录MySQL数据库管理工具&#xff08;如phpMyAdmin&#xff09; 2、打开数据库中的 dede_admin 表&#xff0c;找到管理员记录&#xff0c;将 pwd 字段的值改成 f297a57a5a7…

numpy广播性质

一、核心规则 一维数组本质 shape (n,)的数组是无方向向量&#xff0c;既非严格行向量也非列向量 自动广播机制 在矩阵乘法(或np.dot())中&#xff0c;一维数组会自动调整维度&#xff1a; 前乘时视为行向量 shape (1,n)后乘时视为列向量 shape (n,1) 二、运算类型对比 假…

对Docker的一些基本认识

一、Docker简介 首先Docker 是一个用于开发、交付和运行应用程序的开放平台。它 是一个开源的应用容器化平台&#xff0c;通过轻量级容器技术实现软件的标准化打包、分发与运行。Docker基于 Go语言 &#xff0c;完全使用沙箱机制&#xff0c;相互之间不会有任何接口&#xff0…

数据安全基石:备份文件的重要性与自动化实践

在数字化时代&#xff0c;数据已成为企业和个人不可或缺的重要资产。无论是企业的运营数据、客户资料&#xff0c;还是个人的学习资料、家庭照片&#xff0c;这些数据都承载着巨大的价值。然而&#xff0c;数据的安全问题也日益凸显&#xff0c;硬件故障、软件错误、人为失误以…

Linux:多线程(三.POSIX信号量、生产消费模型、线程池)

目录 1. 生产者消费者模型 1.1 阻塞队列(BlockingQueue) 1.2 一个实际应用的例子 2. POSIX信号量 2.1 引入 2.2 回顾加深理解信号量 2.3 信号量的操作接口 3. 基于循环队列的生产消费模型 3.1 循环队列 3.2 整个项目 4. 线程池 4.1 概念 4.2 线程池实现 1. 生产者…

静态路由实验

一、实验拓扑图&#xff1a; 我们的实验目的是使得全网实现互通。 &#xff08;1)首先我们根据路由器的编号&#xff0c;配置好接口IP地址和 相应的环回地址&#xff1a; R1上的配置&#xff1a; [R1]Int e0/0/0 [R1]ip ad 12.1.1.1 24 [R1]int loopback 0 [R1]ip ad 1.1…