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层

java 复制代码
    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

XML 复制代码
<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表中,定义一个查询

XML 复制代码
    <select id="selectCourseByPaperId" resultType="com.paper.entity.Course">
        select c.*, pc.paper_id from course c
        left join `paper-sys`.paper_course pc on c.id = pc.course_id
        where paper_id = #{paperId}
    </select>

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

在paperMapper.xml中定义一个resultType

XML 复制代码
    <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

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

XML 复制代码
    <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一堆麻烦,但是当代码跑通的那一刻,一切都值得。

相关推荐
小雷君几秒前
SpringBoot 接口开发5个高频踩坑总结
java·spring boot·后端·面试
皙然4 分钟前
Redis八大核心数据类型详解:从底层实现到实战落地
数据库·redis·bootstrap
时光追逐者39 分钟前
一款免费、简单、高效的在线数据库设计工具
数据库·mysql·oracle·sql server
another heaven40 分钟前
【软考 2026 最新版 NoSQL 数据库全分类】
数据库·nosql
满天星830357741 分钟前
【MySQL】表的操作
linux·服务器·数据库·mysql
yashuk1 小时前
Ubuntu 系统下安装 Nginx
数据库·nginx·ubuntu
F1FJJ1 小时前
VS Code 里管理 PostgreSQL,有哪些选择?主流扩展横向对比
网络·数据库·postgresql·容器
我真会写代码1 小时前
SpringBoot自动装配原理:告别繁琐配置,读懂底层逻辑
java·spring boot·mybatis
尽兴-1 小时前
Spring Boot 整合 Elasticsearch 8.x 实战总结(含三种实现方式 + 完整示例)
spring boot·elasticsearch·jenkins
Bdygsl1 小时前
MySQL(8)—— 事务
数据库·mysql