Mybatis多表联查的几种办法

2023-10-29

前言

开发过程中,对数据库多表连接查询是常规操作。Mybatis(plus)在多表连接查询上提供了很好的支持。通常,表与表之间存在四种映射关系:一对一映射、多对一映射、一对多映射、多对多映射。在处理的过程中,多对一和一对一映射一般采用同一种操作方式,一对多和多对多映射一般采用同一种操作方式。而且,对于Mybatis的运用,我们通常使用xml的方式。因此,本文主要介绍xml方式下一对一多表联查和一对多多表联查。

一、一对一多表联查

1.1 两表联查

在数据库中建立学生表专业表两张数据表,并假设一个学生只有一个专业。表结构大致如下

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `phonenum` varchar(20) DEFAULT NULL,
  `mid` int(11) NOT NULL,
  PRIMARY KEY (`stu_id`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

DROP TABLE IF EXISTS `major`;
CREATE TABLE `major` (
  `mid` int(11) NOT NULL AUTO_INCREMENT,
  `mname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`oid`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

在运用Mybatis进行数据查询前,需要先建立实体类模型。在实体类建立的过程中,应当注意:在假设前提下,每名学生有一个专业,在类属性中需包含专业对象。学生实体类大致如下:

public class Student {
	private Integer id;
    private String name;
    private Date birthday;
    private String phonenum;
	private Major major;
	/*此处省略get、set、toString以及构造函数*/
}
public class Major{
	/*暂不考虑专业与学生的对应关系*/
	private Integer mid;
    private String mname;
	/*此处省略get、set、toString以及构造函数*/
}

分别在StudentMapper接口和MajorMapper接口中添加方法

public interface StudentMapper {
    //按id查询Student信息
    public Student findStudentById(Integer id);
}
public interface MajorMapper {
    //按id查询专业信息
    public Major findMajorById(Integer mid);
}

1.1.1 方法一:基于嵌套select的查询

关键来了,我们需要在StudentMapper.xml中的结果映射集中,使用标签来建立学生与专业的对应关系。

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.StudentMapper">
    <!-- id:resultMap的名字  type:方法返回值类型  autoMapper:自动映射 -->
    <resultMap id="stuResult" type="com.domain.Student" autoMapping="true">
        <!-- id标签对应student表的主键  property对应Student类的属性  column对应student表的字段-->
        <id property="id" column="id"></id>
        <result colunm="name" property="name" />
        <result colunm="birthday" property="birthday" />
        <result colunm="phonenum" property="phonenum" />
        <!--
        association:方法返回值是一个对象时使用该标签
        javaType表示返回值类型
        当mybatis 执行完 student表的查询操作后,就会自动执行 MajorMapper接口中的 findMajorById的方法
        把查询得到的信息封装到Student类下的major对象
        -->
        <association property="major" javaType="major" column="mid"  
        		select="com.mapper.MajorMapper.findMajorById" fetchType="eager" >
        </association>
    </resultMap>
            <!-- 接口中对应的方法名 -->
    <select id="findStudentByid" resultMap="stuResult">
        select * from student where id = #{id}
    </select>
</mapper>

MajorMapper.xml文件如下

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.MajorMapper">
    <!-- id:resultMap的名字  type:方法返回值类型  autoMapper:自动映射 -->
    <resultMap id="majResult" type="com.domain.Major" autoMapping="true">
        <id property="mid" column="mid"></id>
        <result colunm="mname" property="mname" />
    </resultMap>
            <!-- 接口中对应的方法名 -->
    <select id="findMajorById" resultMap="majResult">
        select * from student where mid = #{mid}
    </select>
</mapper>

此时,我们调用方法,就能实现两表联查

Student stu = studentMapper.findStudentById(1);

说明:标签中的fetchType为是否启用延迟加载(eager为立即加载,lazy为延迟加载)

1.1.2 方法二:基于join语句的查询

考虑到基于select的两表联查,一次查询需要两条语句。并且与延迟加载一同使用将会产生严重的性能缺陷。下面我们介绍基于join语句的两表联查。

基于join语句的查询,与基于select的查询主要区别在mapper文件,代码如下

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.StudentMapper">
    <resultMap id="stuResult" type="com.domain.Student" autoMapping="true">
        <result colunm="name" property="name" />
        <result colunm="birthday" property="birthday" />
        <result colunm="phonenum" property="phonenum" />
        <association property="major" javaType="major" resultMap="com.mapper.MajorMapper.majResult"></association>
    </resultMap>
            <!-- 接口中对应的方法名 -->
    <select id="findStudentByid" resultMap="stuResult">
        select s.id id, s.name name, s.birthday birthday, s.phonenum phonenum, s.mid mid
        from student s
        join major m
        on s.mid = m.mid
        where s.id = #{id}
    </select>
</mapper>

1.2 Mybatis两张表以上多表联查

对于Mybatis两张表以上的多表联查方法,为以上两种方式的拓展

例如:学生还与家庭住址存在一对一关系,那么我们只需要在实体类中增加地址的实体类对象作为属性,在StudentMapper.xml文件的<resultMap />标签中按照方法一、方法二各自的形式,增加相应的<association />标签,修改select语句,即可实现多表联查。但基于select嵌套的查询存在一定的性能缺陷,而基于join 的查询需要书写较为复杂的SQL语句,因此各有优劣,一般推荐使用基于join的查询方式

二、一对多的多表联查

一对多的多表查询方法,与一对一查询的两种方法较为相似。不同的地方在于(此处假定一个专业对应多名学生):1.一对多情况下,实体类中需要声明对应多个实体的集合属性,如Major实体类中需声明List<Student>属性,而Student实体类中声明的是Major属性(详见1.1中Student实体类定义);2.在MajorMapper.xml文件内的<resultMap />标签内部增加<collection />标签,而StudentMapper.xml相应位置增加的是<association />标签

以基于join语句的查询为例,Major实体类修改为

public class Major{
	private Integer mid;
    private String mname;
    /*建立关联关系*/
    private List<Student> students;
	/*此处省略get、set、toString以及构造函数*/
}

MajorMapper.xml修改为

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.MajorMapper">
    <resultMap id="majResult" type="com.domain.Major" autoMapping="true">
        <id property="mid" column="mid"></id>
        <result colunm="mname" property="mname" />
        
        <collection property="students" javaType="ArrayList" ofType="student" resultMap="com.mapper.StudentMapper.stuResult" /> 
        
    </resultMap>
            <!-- 接口中对应的方法名 -->
    <select id="findMajorById" resultMap="majResult">
        select m.*,s.*
        from major m
        join student s
        on m.mid = s.mid
        where m.mid = #{mid}
    </select>
</mapper>

对于基于select的查询在此不在过多介绍,可参考上文举一反三

三、基于Mybatis-plus的多表联查

众所周知,Mybatis-plus在Mybatis的基础上只做增强,不做修改。因此,以上的方法同样适用。但是,plus可以说将原先的半ORM增强为了真正的ORM,使得对于单表的操作更加方便快捷。基于此,plus的多表查询除以上方法外,还开考虑将单表查询进行组合运用,从而达到多表查询的效果,这有点类似于基于select的查询方法

总结

我个人更偏向于基于join语句的查询方式,在这种方式下,我们可以结合Mybatis的动态SQL编写出强大的数据库交互代码,具有很强的灵活性。另外,如果项目需求较为简单,运用Mybatis-plus搭建项目也是不错的选择

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mybatis多表联查的几种办法 的相关文章

  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 同一配置文件上的两个不同提供程序

    我在用着实体框架 6 1 0 I have 2 家提供者 MysqlClient 和 SQLServerCE 我需要创建2个不同的DBContext 这迫使我创造2个配置类因为mysql有一些不同的东西 但是当我初始化应用程序时 Datab
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 为什么HashMap不能保证map的顺序随着时间的推移保持不变

    我在这里阅读有关 Hashmap 和 Hashtable 之间的区别 http javarevisited blogspot sg 2010 10 difference Between hashmap and html http javar
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 在 MySQL 中存储表情符号的编码问题:如何使用 Prisma ORM 在 NodeJS 中定义字符排序规则?

    亲爱的 Nodejs 专家和数据库专家 我们在 MySQL 数据库中存储表情符号和其他特殊字符时遇到问题 我们使用 Prisma 得到一个错误 这是我们使用的 ORM 参数无法从排序规则 utf8 general ci 转换为 utf8mb
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O

随机推荐

  • C++中sort函数详解

    原文链接点这 0 简介 sort函数用于C 中 对给定区间所有元素进行排序 默认为升序 也可进行降序排序 sort函数进行排序的时间复杂度为n log2n 比冒泡之类的排序算法效率要高 sort函数包含在头文件为 include的c 标准库
  • 性能测试基础概念和分类

    什么是性能测试 gt 在给定环境和场景中进行的测试活动 gt 根据测试结果评判是否存在性能问题 gt 如果存在性能问题 编辑定位性能瓶颈 并提出改进建议 性能不仅仅包括响应时间 还包括资源的占用 性能测试基本流程 1 性能测试需求分析 项目
  • vue项目中使用pdf.js预览pdf文件

    项目要求需要预览pdf文件 网上找了很久 大多数都是推荐pdf js 自己先了解了一下 最后决定用pdf js 但是发现 在vue中使用这个很少 所以我就写这一篇帮助一下vue使用pdfjs的朋友 其实 这和前端框架无关的 直接使用pdf
  • C++ 多态类型

    多态 C 在面向对象中 多态就是不同对象收到相同消息 执行不同的操作 在程序设计中 多态性是名字相同的函数 这些函数执行不同或相似的操作 这样就可以用同一个函数名调用不同内容的函数 简而言之 一个接口 多种方法 多态是以封装和继承为基础的
  • android 注册页面实现

    自己动手做的第一个demo 简单的注册页面的实现 并且注册成功后返回注册信息 适用于android新手基本控件的使用 注册页面的实现 import android os Bundle import android app Activity
  • 如果确定游戏服务器位置,如果确定游戏服务器位置

    如果确定游戏服务器位置 内容精选 换一换 远程登录服务器出现蓝屏或黑屏 可能是由于explorer exe进程异常导致的桌面无法显示 这是由于Windows服务器的explorer exe进程异常导致的 explorer exe是Windo
  • 腾讯混元大模型:新一代人机环境系统智能的发展趋势

    近日 腾讯混元大模型亮相 该通用大语言模型具备强大的中文创作能力 复杂语境下的逻辑推理能力 以及可靠的任务执行能力 同时也可以作为基底模型 为不同产业场景构建专属应用 从可靠 成熟 自研和实用的底层逻辑来看 腾讯混元大模型其实是建立在人机环
  • 算法设计学习记录(一):G-S算法实现稳定匹配

    最近这几周在复习微机原理 不可避免地重燃了对硬件的兴趣 一度想要拿下一张树莓派玩玩 好在这东西不便宜 思来想去还是决定暂时放放 一直有在考虑自己未来的发展方向 自动驾驶还是交通运输 这对我来说是一个很难决定的事情 回过头来想 其实现在确实想
  • 解决 if you already hava 64-bit JDK installed,define a JAVA_HOME variable in Computer>System....

    启动Android studio 弹窗 提示如图 一般是修改studio64 exe vmoptions文件出差 例如我的studio64 exe vmoptions位于C Users 24359 AppData Roaming Googl
  • vue3+scss开启写轮眼

    vue3 scss开启写轮眼 一 相关技术 二 使用步骤 1 安装依赖 2 眼球 3 勾玉 4 旋转动画 5 综合 一 相关技术 采用vue3 vite scss的技术内容进行开发 二 使用步骤 1 安装依赖 代码如下 npm instal
  • vue3+ts+webpack 搭建+环境配置+路由

    一 搭建 vue js webpack的项目 1 vite vue cli 版本在 4 5 0 以上 我用的5 0 4 npm install g vue cli vue V 创建项目 vue create 项目名字 安装依赖运行项目 cd
  • CentOS7 Install nodejs & npm

    1 安装nodejs npm yum install y nodejs npm 2 n Interactively Manage Your Node js Versions npm install g n 安装提示 root localho
  • 如何让 git 使用我选择的编辑器来编辑提交消息?

    问 如何全局配置 git 以使用特定编辑器 例如 vim 来提交消息 答1 一个优秀的自由职业者 应该有对需求敏感和精准需求捕获的能力 而huntsbot com提供了这个机会 设置 Git 的默认编辑器 选一个 在你的 Git 配置中设置
  • msvcp140.dll缺失解决办法

    出现dll缺失 可以考虑如下情况 推荐使用修复功能 能解决大部分情况 如果是开发者 有可能是发布的debug版本 在其它电脑没环境 下面的是各版本对应版本号 推荐使用release版本 可以解决大部分情况 msvcp msvcr vcomp
  • Ubuntu安装solc编译环境步骤

    Ubuntu安装solc编译环境步骤 cmake装过程 安装Z3 安装Boost Solidity安装 Ethereum使用 更进一步的开发 cmake装过程 solc编译器需要的cmake版本要大于3 9 0 所以要安装高于这个版本的cm
  • 论文笔记:FeUdal Networks for Hierarchical Reinforcement Learning

    0 abstract introduction 这也是一篇分层强化学习的论文 分为两层 Manager 上层 设置抽象的goal 这个goal传递给Worker 和H DQN不同 这个goal是由Manager自己学出来的 或者说 FUN不
  • Linux 下系统调用的三种方法

    系统调用 System Call 是操作系统为在用户态运行的进程与硬件设备 如CPU 磁盘 打印机等 进行交互提供的一组接口 当用户进程需要发生系统调用时 CPU 通过软中断切换到内核态开始执行内核系统调用函数 下面介绍Linux 下三种发
  • redis 高级应用之二(Redis的持久化 和 消息的[pub/sub]发布和订阅)

    1 Redis的持久化机制 redis是个支持持久化的内存数据库 也就是说redis要经常把内存中的数据保存到硬盘中来保证持久化 redis持久化方式有两种 snapshotting 快照 也是默认方式 原理 默认redis是会以快照的形式
  • Apache Tomcat 漏洞复现

    文章目录 Apache Tomcat 漏洞复现 1 Tomcat7 弱密码和后端 Getshell 漏洞 1 1 漏洞描述 1 2 漏洞复现 1 3 漏洞利用 1 3 1 jsp小马 1 3 2 jsp大马 1 4 安全加固 2 Aapac
  • Mybatis多表联查的几种办法

    前言 开发过程中 对数据库多表连接查询是常规操作 Mybatis plus 在多表连接查询上提供了很好的支持 通常 表与表之间存在四种映射关系 一对一映射 多对一映射 一对多映射 多对多映射 在处理的过程中 多对一和一对一映射一般采用同一种