当前位置: 首页 > article >正文

Mybatis后端数据库查询多对多查询解决方案

问题场景:

我开发的是一个论文选择系统。

后端用一个论文表paper来存储论文信息。

论文信息中,包含前置课程,也就是你需要修过这些课程才能选择这个论文。

而一个论文对应的课程有很多个。

这样就造成了一个数据库存储的问题。一个paper里面要存储多个course。如何解决这个问题。

方案一:

在创建paper表,存储course,可以将course存储为一个字符串,用指定的分隔符分割。在取出数据的时候。在service层将字符串再重新解析成数组的形式。

这种方案好处是在数据库层面非常方便,但是在service层非常麻烦。

如果需要对paper和course进行修改和删除也将非常的麻烦。需要一遍一遍的解析字符串,修改,重新生成字符串。

而且还有一个重要的问题。如果面对团队合作,这种方法十分受限,因为别人不知道,甚至有一天自己都忘了自己设置的分割符是什么了。

所以这种方法不太可取。

方案二:

我们创建一个中间表。记录这paperId和courseId的对应。

这样你的paper里面就不需要有course等这种字段了。

这种方式的好处就是容易维护,也比较容易理解。

代码实操:

增加

增加paper的时候,只需要获取到paperId和courses数组中的courseId然后调用paper_course中间表的添加操作即可。

这里默认大家熟悉对数据库基础的增删改查。

但是有一个问题。

当在service层插入paper的时候,paperId还没生成。

其实这个无需担心,你只需要先插入paper,然后你在paper里就可以拿到了。

service层

    public void add(Paper paper) {paperMapper.add(paper);addMiddleData(paper);}private void addMiddleData (Paper paper) {Integer paperId = paper.getId();List<Integer> courseIds = paper.getCourseIds();List<Integer> languageIds = paper.getLanguageIds();List<Integer> technologyIds = paper.getTechnologyIds();if (courseIds != null && !courseIds.isEmpty()) {for (Integer courseId : courseIds) {paperCourseMapper.add(new PaperCourse(paperId, courseId));}}if(languageIds != null && !languageIds.isEmpty()) {for (Integer languageId : languageIds) {paperLanguageMapper.add(new PaperLanguage(paperId, languageId));}}if (technologyIds != null && !technologyIds.isEmpty()) {for (Integer technologyId : technologyIds) {paperTechnologyMapper.add(new PaperTechnology(paperId, technologyId));}}}

paperMapper

<mapper namespace="com.paper.mapper.PaperMapper"><insert id="add" parameterType="com.paper.entity.Paper" useGeneratedKeys="true" keyProperty="id">insert into `paper`<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="teacherId != null">teacher_id,</if><if test="studentId != null">student_id,</if><if test="name != null">name,</if><if test="resource != null">resource,</if><if test="content != null">content,</if><if test="studentGroup != null">student_group,</if><if test="type != null">type,</if><if test="gpa != null">gpa,</if><if test="requirement != null">requirement,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id},</if><if test="teacherId != null">#{teacherId},</if><if test="studentId != null">#{studentId},</if><if test="name != null">#{name},</if><if test="resource != null">#{resource},</if><if test="content != null">#{content},</if><if test="studentGroup != null">#{studentGroup},</if><if test="type != null">#{type},</if><if test="gpa != null">#{gpa},</if><if test="requirement != null">#{requirement},</if></trim></insert><delete id="delete">

查询

要查询paper表,需要连接表。

我这里想着重说一下连接表的一个小技巧。

如果只有一个中间表的话,直接用join可能会好一些。然后直接把想查的元素全都查出来就好了。

但是我的场景是,我有三个中间表。

我需要一直join。

并且我要以数组的形式查出来。直接查无法实现这样。

我在course表中,定义一个查询

    <select id="selectCourseByPaperId" resultType="com.paper.entity.Course">select c.*, pc.paper_id from course cleft join `paper-sys`.paper_course pc on c.id = pc.course_idwhere paper_id = #{paperId}</select>

这个查询是查询course表中对应paperId的所有course

在paperMapper.xml中定义一个resultType

    <resultMap id="PaperResultMap" type="com.paper.entity.Paper"><id property="id" column="id" /><result property="teacherId" column="teacher_id" /><result property="studentId" column="student_id" /><result property="name" column="name" /><result property="resource" column="resource" /><result property="content" column="content" /><result property="studentGroup" column="student_group" /><result property="type" column="type" /><result property="gpa" column="gpa" /><result property="requirement" column="requirement" /><collection property="courses" ofType="com.paper.entity.Course"select="com.paper.mapper.CourseMapper.selectCourseByPaperId"column="id"></collection><collection property="languages" ofType="com.paper.entity.Language"select="com.paper.mapper.LanguageMapper.selectLanguageByPaperId"column="id"></collection><collection property="technologies" ofType="com.paper.entity.Technology"select="com.paper.mapper.TechnologyMapper.selectTechnologyByPaperId"column="id"></collection></resultMap>

我这里是关联了三个表。

一个表理解了,三个表一样的。

这个定义了我要的resultType,因为刚刚说了,我要保证我能接受到结果数组。

所以数组部分用collection来接收。

而这个collection连接这刚刚对应的select

也就是这个数组已经被查出来了。

    <select id="selectByPage" resultMap="PaperResultMap">select * from `paper`<where><if test="teacherId != null">and teacher_id = #{teacherId}</if><if test="studentId != null">and student_id = #{studentId}</if></where></select>

最后使用resultMap来定义接受的格式。

那么我们就完成了查询。

是不是非常的优雅呢?

这虽然比join一堆麻烦,但是当代码跑通的那一刻,一切都值得。

相关文章:

Mybatis后端数据库查询多对多查询解决方案

问题场景&#xff1a; 我开发的是一个论文选择系统。 后端用一个论文表paper来存储论文信息。 论文信息中&#xff0c;包含前置课程&#xff0c;也就是你需要修过这些课程才能选择这个论文。 而一个论文对应的课程有很多个。 这样就造成了一个数据库存储的问题。一个paper…...

记一次 Git Fetch 后切换分支为空的情况

Git Fetch 后切换分支为空的情况 在使用 Git 时&#xff0c;我遇到这样的情况&#xff1a;执行 git fetch 后切换分支&#xff0c;发现工作目录是空的&#xff0c;没有任何文件&#xff0c;所以插眼记录一下。 原因分析 git fetch 的作用&#xff1a;git fetch 只会从远程仓库…...

【MySQL排错 】mysql: command not found 数据库安装后无法加载的解决办法

【MySQL排错 】mysql: command not found 数据库安装后无法加载的解决办法 A Solution to Solve Error - mysql: command not found After The Installation of MySQL Community Server By JacksonML 本文简要介绍如何在macOS安装完毕MySQL数据库服务器后&#xff0c;针对无…...

分享一款AI绘画图片展示和分享的小程序

&#x1f3a8;奇绘图册 【开源】一款帮AI绘画爱好者维护绘图作品的小程序 查看Demo 反馈 github 文章目录 前言一、奇绘图册是什么&#xff1f;二、项目全景三、预览体验3.1 截图示例3.2 在线体验 四、功能介绍4.1 小程序4.2 服务端 五、安装部署5.1 快速开始~~5.2 手动部…...

大模型知识蒸馏技术(4)——离线蒸馏

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl离线蒸馏概述 离线蒸馏是知识蒸馏中最早被提出且最为常见的实现方式,其核心在于教师模型和学生模型的训练是分阶段进行的。具体而言,教师模型首先在训练集上进行充分训练,直至收敛,然后利用教…...

解决DeepSeek服务器繁忙的有效方法

全球42%的企业遭遇过AI工具服务器过载导致内容生产中断&#xff08;数据来源&#xff1a;Gartner 2025&#xff09;。当竞品在凌晨3点自动发布「智能家居安装指南」时&#xff0c;你的团队可能正因DeepSeek服务器繁忙错失「净水器保养教程」的流量黄金期⏳。147SEO智能调度系统…...

【C++游戏开发-五子棋】

使用C开发五子棋游戏的详细实现方案&#xff0c;涵盖核心逻辑、界面设计和AI对战功能&#xff1a; 1. 项目结构 FiveChess/ ├── include/ │ ├── Board.h // 棋盘类 │ ├── Player.h // 玩家类 │ ├── AI.h // AI类 │ └── Game.h // 游戏主逻辑 ├── src/ …...

Ubuntu 下 nginx-1.24.0 源码分析 - NGX_MAX_ALLOC_FROM_POOL

NGX_MAX_ALLOC_FROM_POOL 定义在 src\core\ngx_palloc.h #define NGX_MAX_ALLOC_FROM_POOL (ngx_pagesize - 1) 在 src/os/unix/ngx_alloc.h extern ngx_uint_t ngx_pagesize; 这个全局变量定义在 src\os\unix\ngx_alloc.c 中 ngx_uint_t ngx_pagesize; 在 src/os/unix/ngx_…...

等距节点插值公式

目录 等距节点插值公式Newton 前插公式Newton 后插公式 等距节点插值公式 将 Newton 差商插值多项式中各阶差商用相应差分代替&#xff0c;就可得到各种形式的等距节点插值公式&#xff0c;例如常用的前插公式与后插公式。 Newton 前插公式 如果节点 x k x 0 k h ( k 0 , …...

BT401双模音频蓝牙模块如何开启ble的透传,有什么注意事项

BT401音频蓝牙模块如何开启ble的透传&#xff1f; 首先BT401的蓝牙音频模块&#xff0c;分为两个版本&#xff0c;dac版本和iis数字音频版本 DAC版本&#xff1a;就是BT401蓝牙模块【9和10脚】直接输出模拟音频信号&#xff0c;也就是说&#xff0c;直接推动耳机可以听到声音 …...

基于SSM框架的宠物之家系统(有源码+论文!!!)

这个系统可以帮助大家去做设计或者学习,大家可以管我要word版论文🥰这里具体论文内照片、e-r图等等加载不进来, 大家如果想要源码+论文+制定+调试,可以私信我!!(可改别的系统,例如调查问卷系统等等) 目录 第1章 绪论 1.1开发背景 1.2开发工具及语言 第2章 宠物之家系…...

计算机视觉+Numpy和OpenCV入门

Day 1&#xff1a;Python基础Numpy和OpenCV入门 Python基础 变量与数据类型、函数与类的定义、列表与字典操作文件读写操作&#xff08;读写图像和数据文件&#xff09; 练习任务&#xff1a;写一个Python脚本&#xff0c;读取一个图像并保存灰度图像。 import cv2 img cv2.im…...

深入理解正则表达式的预查

深入理解正则表达式的预查(Lookahead and Lookbehind) 在正则表达式中,预查(Lookahead and Lookbehind)是一种强大的工具,允许你在不消耗字符的情况下进行匹配检查。预查可以分为四种类型:正向肯定预查、正向否定预查、反向肯定预查和反向否定预查。 1. 正向肯定预查(…...

网工项目理论1.7 设备选型

本专栏持续更新&#xff0c;整一个专栏为一个大型复杂网络工程项目。阅读本文章之前务必先看《本专栏必读》。 一.交换机选型要点 制式:盒式交换机/框式交换机。功能:二层交换机/三层交换机。端口密度:每交换机可以提供的端口数量。端口速率:百兆/千兆/万兆。交换容量:交换矩阵…...

Gateway中的Filter机制

Gateway中的Filter机制 文章目录 Gateway中的Filter机制Gateway中的Filter机制Gateway Filter 机制的概述核心思想与设计Filter 的两种类型过滤器的生命周期Gateway Filter 的特点Gateway Filter 的意义Gateway Filter 的工作原理核心架构与执行流程执行流程解析过滤器类型的角…...

顺序表常用操作和笔试题

1、顺序表的常用操作 1.1 顺序表的创建 如下代码所示&#xff1a;创建了一个默认空间为10的整型顺序表&#xff0c;如果空间不足则会以1.5倍扩容。 List<Integer> list new ArrayList<>(); 创建一个空间为15的整型顺序表 List<Integer> list2 new ArrayL…...

二.数据治理流程架构

1、数据治理流程架构核心思想&#xff1a; 该图描绘了一个以数据标准规范体系为核心&#xff0c;大数据生命周期管理为主线&#xff0c;数据资源中心为依托&#xff0c;并辅以数据质量管理和大数据安全与隐私管理的数据治理流程架构。它旨在通过规范化的流程和技术手段&#x…...

【Java】泛型与集合篇(二)

泛型与集合(二) Set 接口及实现类HashSet 类特点内部实现构造方法LinkedHashSet 类基本概念特点构造方法常用方法适用场景用 Set 对象实现集合运算TreeSet 类特性构造方法常用方法注意事项对象顺序自然排序定制排序注意事项Queue 接口及实现类Queue 接口定义与特点常用方法常…...

解锁机器学习核心算法 | 线性回归:机器学习的基石

在机器学习的众多算法中&#xff0c;线性回归宛如一块基石&#xff0c;看似质朴无华&#xff0c;却稳稳支撑起诸多复杂模型的架构。它是我们初涉机器学习领域时便会邂逅的算法之一&#xff0c;其原理与应用广泛渗透于各个领域。无论是预测房价走势、剖析股票市场波动&#xff0…...

CSS 底部颗粒磨砂特效

参考&#xff1a;element-plus的顶部效果 background-image: radial-gradient(transparent 1px, var(--bg-color) 1px); background-size: 4px 4px; backdrop-filter: saturate(50%) blur(4px); 注意点&#xff1a;var(--bg-color) 改为跟你背景色相同的即可。 其他自己看情况…...

QT自定义扫描控件,支持任意方位拖动和拖动扫描范围。

部分代码&#xff1a; void FishControlForm::paintEvent(QPaintEvent *event) {QPainter p(this);p.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);p.translate(m_centerPoint);//bgp.setPen(Qt::white);p.drawEllipse(-m_radius,-m_radius,m_rad…...

Ubuntu18.04安装rvm、ruby2.6.5和rails5.2.6

系统环境&#xff1a;Ubuntu 18.04 一、安装前准备 1. sudo apt update 2. sudo apt upgrade 如果提示abort&#xff0c;忽略。 3. sudo apt install sqlite3 gnupg curl git libpq-dev 二、安装rvm ruby版本管理器 1.切换管理员模式 sudo su 2.安装软件签名公钥 gpg…...

燧光 XimmerseMR SDK接入Unity

官网SDK文档连接&#xff1a; RhinoX Unity XR SDK 一&#xff1a;下载SDK 下载链接&#xff1a;RhinoX Unity XR SDK 二&#xff1a;打开Unity项目&#xff0c;添加Package 1、先添加XR Core Utilties包和XR Interaction Toolkit包 2、导 2、再导入下载好的燧光SDK 三&…...

罗德与施瓦茨ZNB20,矢量网络分析仪9KHz-20GHz

罗德与施瓦茨ZNB20矢量网络分析仪9KHz-20GHz R&SZNB20矢量网络分析仪 产品型号: ZNB20 产品品牌&#xff1a;罗德与施瓦茨 R&S 产品名称: 矢量网络分析仪 频率范围&#xff1a;9kHz - 20GHz R&S ZNB 矢量网络分析仪 良好的测量速度、动态范围和操作方便性&am…...

突破平面限制:低空经济激活城市土地“立体生长力”

蓄锐行&#xff1a;我深耕于低空经济领域&#xff0c;同时对IOT技术有着深入的理解&#xff0c;而在AI的探索性研究上&#xff0c;我也已迈出坚实的步伐&#xff0c;虽起步不久&#xff0c;却满怀热情与憧憬。平日里&#xff0c;我热衷于撰写关于低空经济的文章&#xff0c;分享…...

可调节图片参数,解决图片模糊及尺寸过小问题的工具

软件介绍 你是否正为图片模糊、尺寸太小而烦恼&#xff1f;别担心&#xff0c;有这样一款神器能帮你轻松解决。它能精准调节图片参数&#xff0c;即便原本模糊不清的图片&#xff0c;经它处理后也能变得高清锐利&#xff0c;瞬间让图片焕然一新。而且&#xff0c;它还具备导出…...

React 与 Vue 对比指南 - 上

React 与 Vue 对比指南 - 上 本文将展示如何在 React 和 Vue 中实现常见功能&#xff0c;从基础渲染到高级状态管理 Hello 分别使用 react 和 vue 写一个 Hello World&#xff01; react export default () > {return <div>Hello World!</div>; }vue <…...

✨2.快速了解HTML5的标签类型

✨✨HTML5 的标签类型丰富多样&#xff0c;每种类型都有其独特的功能和用途&#xff0c;以下是一些常见的 HTML5 标签类型介绍&#xff1a; &#x1f98b;结构标签 &#x1faad;<html>&#xff1a;它是 HTML 文档的根标签&#xff0c;所有其他标签都包含在这个标签内&am…...

力扣 买卖股票的最佳时机

贪心算法典型例题。 题目 做过股票交易的都知道&#xff0c;想获取最大利润&#xff0c;就得从最低点买入&#xff0c;最高点卖出。这题刚好可以用暴力&#xff0c;一个数组中找到最大的数跟最小的数&#xff0c;然后注意一下最小的数在最大的数前面即可。从一个数组中选两个数…...

【SQL】SQL多表查询

&#x1f384;概念 一般我们说的多表查询都涉及外键和父子表之间的关系。比如一对多:一般前面指的是父表后面指的是子表。 ⭐分类 一对多(多对一) 多对多 一对一 ⭐一对多 &#x1f4e2;案例&#xff1a;部门与员工的关系 &#x1f4e2;关系&#xff1a;一个部门对应多个员…...