Java-08 深入浅出 MyBatis - 多对多模型 SqlMapConfig 与 Mapper 详细讲解测试
点一下关注吧!!!非常感谢!!持续更新!!!
大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

目前已经更新到了:
- MyBatis(正在更新)
多对多
在数据库设计中,“多对多”关系是指两张表中的记录可以互相关联,多条记录可以关联多条记录。例如,“学生”表和“课程”表之间的关系可能是多对多,因为一个学生可以选修多门课程,而一门课程也可能被多名学生选修。
要实现多对多的关系,通常需要使用一个 中间表(关联表)。这个中间表起到桥梁的作用,将两个表的记录通过其主键关联起来。
多对多关系的特点
- 双向性:A可以关联多个B,同时B也可以关联多个A。
- 需要中间表:为了表示这种关系,通常使用一个中间表来维护关联。
- 灵活性高:多对多关系非常适合用来表示复杂的业务逻辑,尤其是在需要动态添加或修改关系时。
多对多关系的扩展
添加额外字段
中间表可以扩展为更多功能。例如,可以为选课添加时间戳、成绩字段、是否通过等。
索引优化
为中间表中的外键添加索引,提高查询性能。
ORM 框架支持
现代框架(如 Hibernate、Django ORM)支持多对多关系的自动管理。在代码中只需要声明模型的关系,底层会自动生成并管理中间表。
查询模型

用户表和角色的关系,一个用户有多个角色,一个角色被多个用户使用。
多对多的查询的需求,查询用户同时查询出该用户所有的角色。
创建表
wzk_user_role
CREATE TABLE `wzk_user_role` (`id` int(11) NOT NULL,`user_id` int(11) NOT NULL,`role_id` int(11) NOT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
wzk_role
CREATE TABLE `wzk_role` (`id` int(11) NOT NULL,`rolename` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
插入数据
wzk_user_role
INSERT INTO wzk_user_role
VALUES(1, 1, 1);INSERT INTO wzk_user_role
VALUES(1, 2, 2);
wzk_role
INSERT INTO wzk_role
VALUES(1, "ADMIN");INSERT INTO wzk_role
VALUES(2, "USER");
查询语句
select u.*,r.*,r.id rid from wzk_user u
left join wzk_user_role ur on u.id=ur.user_id
inner join wzk_role r on ur.role_id=r.id;
执行结果如下所示:

创建类
WzkUser
这里需要加入新的字段
package icu.wzk.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;
import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkUser {private int id;private String username;private String password;private Date birthday;private List<WzkOrder> orderList;private List<WzkRole> roleList;
}
对应的截图如下所示:

WzkRole
package icu.wzk.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkRole {private Integer id;private String rolename;
}
对应的截图如下所示:

UserMapper
package icu.wzk.mapper;import icu.wzk.model.WzkUser;import java.util.List;public interface UserMapper {List<WzkUser> findAll();List<WzkUser> findAllUserAndRole();
}
对应的截图如下所示:

UserMapper.xml
<resultMap id="userRoleMap" type="icu.wzk.model.WzkUser"><result column="id" property="id"></result><result column="username" property="username"></result><result column="password" property="password"></result><result column="birthday" property="birthday"></result><collection property="roleList" ofType="icu.wzk.model.WzkRole"><result column="rid" property="id"></result><result column="rolename" property="rolename"></result></collection>
</resultMap><select id="findAllUserAndRole" resultMap="userRoleMap">SELECT u.*, r.*, r.id ridFROM wzk_user uLEFT JOIN wzk_user_role ur on u.id=ur.user_idINNER JOIN wzk_role r on ur.role_id=r.id;
</select>
对应的截图如下所示:

编写代码
package icu.wzk;import icu.wzk.mapper.UserMapper;
import icu.wzk.model.WzkUser;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class WzkIcu10 {public static void main(String[] args) throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List<WzkUser> dataList = userMapper.findAllUserAndRole();dataList.forEach(System.out::println);sqlSession.close();}
}
代码的截图如下所示:

运行结果
运行上面的代码,控制台输出的结果如下所示:
WzkUser(id=1, username=wzk, password=icu, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=null, roleList=[WzkRole(id=1, rolename=ADMIN)])
WzkUser(id=2, username=wzk2, password=icu2, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=null, roleList=[WzkRole(id=2, rolename=USER)])
24/11/12 18:02:33 DEBUG jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@15b204a1]
对应的截图如下所示:

注意事项
- 索引优化:为中间表的外键字段创建索引,提升查询性能。
- 关系约束:使用外键约束维护数据一致性,避免孤立数据。
- 批量操作:在大规模插入、更新时,尽量使用批量操作,提升效率。
- 软删除:中间表可以设计“软删除”标志位,用于保留历史记录。
大表的分表与分库
问题背景
在超大规模应用中,单表可能变得过于庞大,导致性能问题。
解决方法
- 垂直分表:将额外字段分离,减少单表宽度。
- 水平分表:将记录按学生或课程拆分到多个表。
- 分库:将不同表分布在多个数据库实例上。
日志和监控
问题背景
多对多关系中的数据修改频繁,容易引入错误,例如重复记录、孤立记录等。
解决方法
- 日志记录:记录每次数据操作的详细信息。
- 监控工具:定期检查中间表是否存在孤立记录或重复记录。
暂时小结
优化多对多关系模型需要从多个方面入手:
- 提升性能:通过索引、分区、批量操作等方式优化查询和更新。
- 保证数据一致性:通过外键约束和事务处理避免数据异常。
- 提高灵活性:通过软删除和日志记录保留历史数据,支持恢复和审计。
- 应对大数据场景:通过分区、分表或分库设计,确保系统扩展性。
相关文章:
Java-08 深入浅出 MyBatis - 多对多模型 SqlMapConfig 与 Mapper 详细讲解测试
点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatisÿ…...
Vue.js修饰符
Vue.js 是一个渐进式JavaScript框架,用于构建用户界面。在Vue.js中,修饰符(Modifiers)是一种增强指令行为的工具,它们可以改变指令的默认行为。本文将详细讲解Vue.js中的修饰符,并提供实际示例,…...
【数据分享】2024年我国省市县三级的住宿服务设施数量(8类住宿设施/Excel/Shp格式)
宾馆酒店、旅馆招待所等住宿服务设施的配置情况是一个城市公共基础设施完善程度的重要体现,一个城市住宿服务设施种类越丰富,数量越多,通常能表示这个城市的公共服务水平越高! 本次我们为大家带来的是我国各省份、各地级市、各区…...
【含文档】基于.NET的医院医保管理系统(含源码+数据库+lw)
1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 主要技术:mysql,vue 2.视频演示地址 3.功能 系统定义了两个角色:管理员和用户。 管理员进入主界面&…...
c++源码阅读__smart_ptr__正文阅读
文章目录 简介源码解析1. 引用计数的实现方式2. deleter静态方法的赋值时间节点3.make_smart的实现方式 与 好处4. 几种构造函数4.1 空构造函数4.2 接收指针的构造函数4.3 接收指针和删除方法的构造函数 , 以及auto进行模板lambda的编写4.4 拷贝构造函数4.5 赋值运算符 5. rele…...
图形化界面MySQL(MySQL)(超级详细)
1.官网地址 MySQL :: Download MySQL Workbench 1.1在Linux直接点击NO thanks..... 下载完后是这个页面 1.2任何远端登录,再把jj数据库给授权 1.3建立新用户 进行连接 点击这个就运行了 只执行show tables;要先选中 圆圈处支持自己输入 点击这个就执…...
【2024 Optimal Control 16-745】Julia语法
Lecture 2 θ和它的导数符号是通过 Julia 中的变量命名方式实现的 变量 θ 的输入: 在 Julia 中,θ 是一个合法的变量名,就像普通的字母 x 或 y 一样。要输入 θ,可以使用以下方法: 在 Jupyter Notebook 或 Julia REP…...
Opencv+ROS实现摄像头读取处理画面信息
一、工具 ubuntu18.04 ROSopencv2 编译器:Visual Studio Code 二、原理 图像信息 ROS数据形式:sensor_msgs::Image OpenCV数据形式:cv:Mat 通过cv_bridge()函数进行ROS向opencv转换 cv_bridge是在ROS图像消息和OpenCV图像之间进行转…...
网络安全,文明上网(2)加强网络安全意识
前言 在当今这个数据驱动的时代,对网络安全保持高度警觉已经成为每个人的基本要求。 网络安全意识:信息时代的必备防御 网络已经成为我们生活中不可或缺的一部分,信息技术的快速进步使得我们对网络的依赖性日益增强。然而,网络安全…...
深度学习实战图像缺陷修复
这里写目录标题 概述1. 图像缺陷修复的研究背景2. 传统图像缺陷修复方法的局限性(1) 基于纹理合成的方法(2) 基于偏微分方程(PDE)的方法 3. 深度学习在图像缺陷修复中的兴起(1) 深度学习的基本思路(2) 深度学习方法的优势(3) 关键技术的引入 4. 深度学习…...
jenkins 2.346.1最后一个支持java8的版本搭建
1.jenkins下载 下载地址:Index of /war-stable/2.346.1 2.部署 创建目标文件夹,移动到指定位置 创建一个启动脚本,deploy.sh #!/bin/bash set -eDATE$(date %Y%m%d%H%M) # 基础路径 BASE_PATH/opt/projects/jenkins # 服务名称。同时约定部…...
【数据库原理】创建与维护表,DDL数据定义语言
数据描述语言(数据定义语言) 就是管理数据库整个库,整个表,表的属性列的语句。 常用词儿就是数据库或表的增删改查:CREATE创建、DROP删除、ALTER修改、SHOW查看、USE进入表。 表的字段控制:PRIMARY KEY主键…...
驾驭Go语言中的不确定性:深入错误处理机制
驾驭Go语言中的不确定性:深入错误处理机制 在Go语言的编程世界中,错误处理是确保程序健壮性的关键。Go语言通过显式的错误返回值和panic/recover机制,提供了一套独特的错误处理策略。本文将深入探讨Go语言中的错误处理,包括原理、技术细节和实际案例,帮助读者在实际编程中…...
3D Gaussian Splatting在鱼眼相机中的应用与投影变换
paper:Fisheye-GS 1.概述 3D 高斯泼溅 (3DGS) 因其高保真度和实时渲染而备受关注。然而,由于独特的 3D 到 2D 投影计算,将 3DGS 适配到不同的相机型号(尤其是鱼眼镜头)带来了挑战。此外,基于图块的泼溅效率低下,尤其是对于鱼眼镜头的极端曲率和宽视野,这对于其更广泛…...
【Unity踩坑】在Mac上安装Cocoapods失败
在集成Unity Ad时,如果是第一次在iOS上集成,会在Mac上安装Cocoapods。 安装时提示下面的错误: Error installing cocoapods:The last version of drb (> 0) to support your Ruby & RubyGems was 2.0.5. Try installing it with gem…...
uni-app 认识条件编译,了解多端部署
一. 前言 在使用 uni-app 进行跨平台开发的过程中,经常会遇到需要针对不同平台或不同环境进行条件编译的情况。条件编译是一种在编译过程中根据指定条件选择不同代码路径的技术,可以帮助我们在不同平台或环境下编写不同的代码,以适应不同的平…...
SPA 首屏加载慢的原因及解决方案:结合实际项目的详细讲解
在现代前端开发中,单页面应用程序 (SPA) 的首屏加载速度是用户体验的关键因素之一。首屏加载慢会直接影响用户对网站的第一印象,甚至导致用户流失。因此,优化首屏加载速度是每个前端开发者需要重点关注的内容。 1. 什么是首屏加载? 首屏加载指的是用户访问一个网站或应用…...
vue3+ts el-tabel 搜索组件
爷爷页面 <template> <searchstyle"z-index: 9999":options"options"placeholder"请选择时间,或输入名称、单选、多个勾选、模糊查询"search"onSearch"></search> </template> <script lan…...
leetcode 排序算法汇总
快速排序 def quicksort(arr): if len(arr) < 1: return arr else: pivot arr[len(arr) // 2] # 选择中间值作为基准 left [x for x in arr if x < pivot] # 小于基准的放左边 middle [x for x in arr if x pivot] # 等…...
【C】错误的变量定义导致sprintf()输出错误
问题描述 刚刚写一个用AT指令透传相关的函数,需要用到sprintf()拼接字符串。 结果发现sprintf()拼接出来的内容是错误的,简化后的代码如下: const char AT_CIPSEND_FIX_LENGTH_HEADER[11] "ATCIPSEND"; // 错误的࿰…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
