连表查询-mybatis

关于关联查询

    首先,请准备一些测试数据,使得:存在若干条用户数据,存在若干条角色数据,某个用户存在与角色的关联,最好有些用户有多个关联,又有些用户只有1个关联,还有些用户没有关联。

假设存在需求:根据id查询某用户信息时,也查出该用户归属于哪几种角色。

**测试数据参考:**


truncate admin;
truncate admin_role;
truncate role;
truncate permission;insert into admin (username, password) values ('admin001', '123456');
insert into admin (username, password) values ('admin002', '123456');
insert into admin (username, password) values ('admin003', '123456');
insert into admin (username, password) values ('admin004', '123456');
insert into admin (username, password) values ('admin005', '123456');
insert into admin (username, password) values ('admin006', '123456');
insert into admin (username, password) values ('admin007', '123456');
insert into admin (username, password) values ('admin008', '123456');
insert into admin (username, password) values ('admin009', '123456');
insert into admin (username, password) values ('admin010', '123456');
insert into admin (username, password) values ('admin011', '123456');
insert into admin (username, password) values ('admin012', '123456');
insert into admin (username, password) values ('admin013', '123456');
insert into admin (username, password) values ('admin014', '123456');
insert into admin (username, password) values ('admin015', '123456');
insert into admin (username, password) values ('admin016', '123456');
insert into admin (username, password) values ('admin017', '123456');
insert into admin (username, password) values ('admin018', '123456');
insert into admin (username, password) values ('admin019', '123456');
insert into admin (username, password) values ('admin020', '123456');insert into permission (name, value, description) values
('商品-商品管理-读取', '/pms/product/read', '读取商品数据,含列表、详情、查询等'),
('商品-商品管理-编辑', '/pms/product/update', '修改商品数据'),
('商品-商品管理-删除', '/pms/product/delete', '删除商品数据'),
('后台管理-管理员-读取', '/ams/admin/read', '读取管理员数据,含列表、详情、查询等'),
('后台管理-管理员-编辑', '/ams/admin/update', '编辑管理员数据'),
('后台管理-管理员-删除', '/ams/admin/delete', '删除管理员数据');insert intorole (name) values
('超级管理员'), ('系统管理员'), ('商品管理员'), ('订单管理员');insert into admin_role (admin_id, role_id) values
(1, 1), (1, 2), (1, 3), (1, 4),
(2, 1), (2, 2), (2, 3),
(3, 1), (3, 2),
(4, 1);
```

本次查询需要执行的SQL语句大致是:


select *
from admin
left join admin_role on admin.id=admin_role.admin_id
left join role on admin_role.role_id=role.id
where admin.id=?

通过测试运行,可以发现(必须基于以上测试数据):

- 当使用的id值为1时,共查询到4条记录,并且用户的基本信息是相同的,只是与角色关联的数据不同
- 当使用的id值为2时,共查询到3条记录
- 当使用的id值为3时,共查询到2条记录
- 当使用其它有效用户的id时,共查询到1条记录

其实,这种查询期望的结果应该是:


public class xxx {// 用户基本信息的若干个属性,例如用户名、密码等// 此用户的若干个角色数据,可以使用 List<?>
}

则可以先创建“角色”对应的数据类型:


public class Role {private Long id;private String name;private String description;private Integer sort;private LocalDateTime gmtCreate;private LocalDateTime gmtModified;// Setters & Getterss// toString()
}

再创建用于封装此次查询结果的类型:


public class AdminDetailsVO {private Long id;private String username;private String password;private String nickname;private String avatar;private String phone;private String email;private String description;private Integer isEnable;private String lastLoginIp;private Integer loginCount;private LocalDateTime gmtLastLogin;private LocalDateTime gmtCreate;private LocalDateTime gmtModified;private List<Role> roles;// Setters & Getterss// toString()
}

接下来,可以在`AdminMapper`接口中添加抽象方法:


AdminDetailsVO getDetailsById(Long id);

需要注意,由于此次关联了3张表一起查询,结果集中必然出现某些列的名称是完全相同的,所以,在查询时,不可以使用星号表示字段列表(因为这样的结果集中的列名就是字段名,会出现相同的列名),而是应该至少为其中的一部分相同名称的列定义别名,例如:


selectadmin.id,admin.username,admin.password,admin.nickname,admin.avatar,admin.phone,admin.email,admin.description,admin.is_enable,admin.last_login_ip,admin.login_count,admin.gmt_last_login,admin.gmt_create,admin.gmt_modified,role.id AS role_id,role.name AS role_name,role.description AS role_description,role.sort AS role_sort,role.gmt_create AS role_gmt_create,role.gmt_modified AS role_gmt_modified
from admin
left join admin_role on admin.id=admin_role.admin_id
left join role on admin_role.role_id=role.id
where admin.id=1;

在Mybatis处理中此查询时,并不会那么智能的完成结果集的封装,所以,必须自行配置`<resultMap>`用于指导Mybatis完成封装!


<resultMap id="DetailsResultMap" type="xx.xx.xx.xx.AdminDetailsVO"><!-- 在1对多、多对多的查询中,即使名称匹配的结果,也必须显式的配置 --><!-- 主键字段的结果必须使用id节点进行配置,配置方式与result节点完全相同 --><id column="id" property="id" /><result column="gmt_create" property="gmtCreate" /><!-- 需要使用collection节点配置1对多中“多”的数据 --><collection property="roles" ofType="xx.xx.xx.Role"><id column="role_id" property="id" /><result column="gmt_create" property="gmtCreate" /></collection>
</resultMap>

的查询SQL语句,并使用以上的`<resultMap>`封装结果即可!


<sql id="DetailsQueryFields"><if test="true">admin.id,admin.username,admin.password,admin.nickname,admin.avatar,admin.phone,admin.email,admin.description,admin.is_enable,admin.last_login_ip,admin.login_count,admin.gmt_last_login,admin.gmt_create,admin.gmt_modified,role.id AS role_id,role.name AS role_name,role.description AS role_description,role.sort AS role_sort,role.gmt_create AS role_gmt_create,role.gmt_modified AS role_gmt_modified</if>
</sql>

<resultMap id="DetailsResultMap" type="cn.tedu.mybatis.AdminDetailsVO">
    <!-- 在1对多、多对多的查询中,即使名称匹配的结果,也必须显式的配置 -->
    <!-- 主键字段的结果必须使用id节点进行配置,配置方式与result节点完全相同 -->

    <id column="id" property="id" /><result column="username" property="username" /><result column="password" property="password" /><result column="nickname" property="nickname" /><result column="avatar" property="avatar" /><result column="phone" property="phone" /><result column="email" property="email" /><result column="description" property="description" /><result column="is_enable" property="isEnable" /><result column="last_login_ip" property="lastLoginIp" /><result column="login_count" property="loginCount" /><result column="gmt_last_login" property="gmtLastLogin" /><result column="gmt_create" property="gmtCreate" /><result column="gmt_modified" property="gmtModified" /><!-- 需要使用collection节点配置1对多中“多”的数据 --><collection property="roles" ofType="cn.tedu.mybatis.Role"><id column="role_id" property="id" /><result column="role_name" property="name" /><result column="role_description" property="description" /><result column="role_sort" property="sort" /><result column="role_gmt_create" property="gmtCreate" /><result column="role_gmt_modified" property="gmtModified" /></collection>
</resultMap>
<select id="getDetailsById" resultMap="DetailsResultMap">select <include refid="DetailsQueryFields" />from adminleft join admin_role on admin.id=admin_role.admin_idleft join role on admin_role.role_id=role.idwhere admin.id=#{id}
</select>

总结:

  MyBatis是一个流行的Java持久化框架,它提供了一种方便的方式来执行数据库查询,并支持各种连表查询。在本文中,我将为您详细介绍MyBatis的连表查询方式,并解释在XML中如何编写SQL语句以及实体类的写法,以及需要注意的事项。

连表查询是通过在SQL语句中使用JOIN子句来实现的。在MyBatis中,有以下几种常见的连表方式:

  1. 内连接(INNER JOIN):只返回满足连接条件的行。
  2. 左连接(LEFT JOIN):返回左表中的所有行,以及满足连接条件的右表中的行。
  3. 右连接(RIGHT JOIN):返回右表中的所有行,以及满足连接条件的左表中的行。
  4. 全连接(FULL JOIN):返回左右表中的所有行,如果某行在另一表中没有匹配的行,则用NULL填充。

在XML中编写连表查询的SQL语句时,可以使用以下方式:

<select id="selectByExample" parameterType="com.example.entity.Example" resultMap="com.example.mapper.ExampleResultMap">SELECT * FROM table1 t1JOIN table2 t2 ON t1.id = t2.id
</select>

在这个例子中,我们使用了JOIN子句将table1table2进行连接,通过ON关键字指定了连接条件。

在实体类中,我们可以使用嵌套对象来表示连接的表。例如,如果我们有table1table2两个表,我们可以创建以下两个实体类:

public class Table1 {private int id;private String name;private Table2 table2;// getter and setter
}public class Table2 {private int id;private String value;// getter and setter
}

在上面的例子中,Table1实体类包含了一个类型为Table2的属性table2,这样我们就可以通过连表查询获取到table1table2之间的关联数据。

需要注意的是,在进行连表查询时,要确保表之间的连接条件是正确的,并且在数据库中存在相应的关联关系。此外,还要注意避免查询结果过大导致性能问题,可以使用分页或其他限制条件来控制查询返回的数据量。

总结:

  • MyBatis支持多种连表查询方式,包括内连接、左连接、右连接和全连接。
  • 在XML中编写连表查询的SQL语句时,可以使用JOIN子句,并通过ON关键字指定连接条件。
  • 在实体类中,可以使用嵌套对象来表示连接的表。
  • 在进行连表查询时,需要确保连接条件正确,并且注意性能问题。

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

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

相关文章

XML常用介绍

XML代表可扩展标记语言&#xff08;eXtensible Markup Language&#xff09;&#xff0c;它是一种类似于HTML的标记语言。XML用于提供数据描述格式&#xff0c;适用于不同应用程序之间的数据交换&#xff0c;而这种交换不依赖于预定义的数据结构集合&#xff0c;从而增强了可扩…

产品说明文件的二维码怎么做?扫码看文件在线生成技巧

现在很多企业会把产品说明书的文件做成二维码后&#xff0c;印刷到产品包装或者宣传展板上&#xff0c;让其他人通过扫码来查看说明&#xff0c;有效的提高了用户体验。那么文件二维码制作的方法和步骤可能有很多小伙伴都不太清楚&#xff0c;那么今天小编通过本篇文章来给大家…

城市基础信息管理系统 (VB版电子地图源码/公交车线路图/超市平面图)-143-(代码+程序说明)

转载地址http://www.3q2008.com/soft/search.asp?keyword143 请访问 以下地址,查看最新版本, 新增加支持 建筑物 距离测量, 鸟瞰, 地图放大缩小, VB完善地图扩充程序(城市街道基础信息管理系统 )-362-&#xff08;代码&#xff0b;论文&#xff09; 这套系统印象深刻 因为,写…

[云原生] K8s之ingress

1.Ingress的相关知识 1.1 Ingress的简介 service的作用体现在两个方面&#xff0c;对集群内部&#xff0c;它不断跟踪pod的变化&#xff0c;更新endpoint中对应pod的对象&#xff0c;提供了ip不断变化的pod的服务发现机制&#xff1b;对集群外部&#xff0c;他类似负载均衡器…

VideoDubber时长可控的视频配音方法

本次分享由中国人民大学、微软亚洲研究院联合投稿于AAAI 2023的一篇专门为视频配音任务定制的机器翻译的工作《VideoDubber: Machine Translation with Speech-Aware Length Control for Video Dubbing》。这个工作将电影或电视节目中的原始语音翻译成目标语言。 论文地址&…

软件测试 基础(2)

文章目录 1. 软件测试&软件开发生命周期2. 如何描述一个 BUG3. 如何定义 BUG 的级别4. BUG 的生命周期5. 如何进行第一次测试6. 测试的执行和 BUG 管理7. 产生争执怎么办&#xff08;处理人际关系&#xff09; 1. 软件测试&软件开发生命周期 软件测试的生命周期&#…

Matplotlib图形配置--自定义坐标刻度

文章目录 自定义坐标刻度编程要求代码解释 自定义坐标刻度 虽然matplotlib默认的坐标轴定位器与格式生成器可以满足大部分需求&#xff0c;但是并非对每一幅图都合适。 主次要刻度 学习前最好先对matplotlib图形的对象层级有深入了解。 matplotlib的figure对象是一个盛放图形…

Oracle集群ASM磁盘扩容

先通过lsblk来查看集群两端磁盘是否扩容成功 lsblk -a查看自己两边磁盘UUID是否相同(for i in 后面为磁盘sd后字母名) for i in x y z aa ab ac ad ae do echo "KERNEL\"sd*\", SUBSYSTEM\"block\", PROGRAM\"/lib/udev/scsi_id --whitelist…

Vue 3中的ref:响应式变量的强大工具

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

jeecgboot 开放页面权限,免登录访问

前端需要配置路由和添加白名单 1、配置路由 2、 在permission.js里&#xff0c;把刚才的路由添加到白名单 3、 后端需要把该页面涉及到的接口排除权限拦截 比如我这个页面涉及到两个接口&#xff1a; 那么就在后端的excludeUrls把这两个接口加进去。 前端后端都设置好了&…

PostgreSQL教程(二十九):服务器管理(十一)之高可用、负载均衡和复制

数据库服务器可以一起工作&#xff0c;这样如果主要的服务器失效则允许一个第二服务器快速接手它的任务&#xff08;高可用性&#xff09;&#xff0c;或者可以允许多个计算机提供相同的数据&#xff08;负载均衡&#xff09;。理想情况下&#xff0c;数据库服务器能够无缝地一…

Linux系统运维脚本:检查登录用户是否过多 (比如超过20个),使用uptime,who,cron等命令查看登录用户的数量

目 录 一、问题 二、解决方法 1、通过统计登录用户来发现非法入侵者 2、脚本实现登录用户数超过阈值&#xff0c;给出提醒 3、定期运行脚本&#xff0c;让提醒及时有效 一、问题 Linux的服务器放在公网上&#xff0c;很多人需要访问这个服务器&#xff0c;知道…

AI皮肤测试的基本原理

人工智能测试皮肤的实现原理通常涉及计算机视觉和机器学习技术。以下是一般的实现步骤和原理&#xff0c;涉及数据收集、特征提取、模型训练和优化等多个步骤&#xff0c;利用这些步骤中的技术手段来实现对皮肤状况的识别和分类。北京木奇移动技术有限公司&#xff0c;专业的软…

在用Java写算法的时候如何加快读写速度

对于解决该方法我们一般如下操作&#xff0c;不需要知道为什么&#xff0c;有模板&#xff08;个人观点&#xff09; 使用BufferedReader代替Scanner&#xff1a;Scanner类在读取大量输入时性能较差&#xff0c;而BufferedReader具有更高的读取速度。可以使用BufferedReader的r…

车规芯片为什么需要信息安全(2)

目录 1.车规芯片的信息安全应该从什么地方考虑 1.1 芯片硬件安全防护能力 1.2 车规芯片的信息安全服务

Yolov8将.pt文件转换为tensorRt的.trt文件(模型部署)

我的环境 确保自己已经有cuda和cudnn的环境基础上进行。 cuda:11.7cudnn:适合cuda的版本Anaconda3 [python 3.10]TensorRt-8.6.1 安装TensorRt环境 查看自己的cuda环境&#xff0c;去官网下载适合的win版本。 官网地址 下载后解压&#xff0c;将解压后lib目录添加到环境变…

总结:Spring循环依赖详解与@Lazy注解使用详解

总结&#xff1a;Spring循环依赖详解与Lazy注解使用详解 一前提知识储备&#xff1a;1.Spring Bean生命周期机制&#xff08;IOC&#xff09;2.Spring依赖注入机制&#xff08;DI&#xff09;&#xff08;1&#xff09;Autowired注解标注属性set方法注入&#xff08;2&#xff…

Altium Designer如何对走线模式进行切换

AD软件提供了比较智能的走线模式切换功能&#xff0c;可以根据个人习惯进行切换&#xff0c;能有效的提高了PCB设计效率。 点击界面右上角系统参数的图标 或者在pcb界面中使用快捷键OP进入到优选项界面&#xff0c;然后选中 PCB Editor-Interactive Routing&#xff0c;在布线…

【C++】面向过程与面向对象

文章目录 1. 面向过程与面向对象2. 类&#xff08;class&#xff09;类的作用域 3. 访问限定符封装 4. 类的实例化5. this指针 1. 面向过程与面向对象 C语言是面向过程&#xff08;procedure-oriented&#xff09;的语言&#xff0c;分析出求解问题的步骤&#xff0c;通过函数…

mmdetection如何计算准确率、召回率、F1值

1、训练 python tools/train.py configs/fcos/fcosrdweed3.py 2、测试 这一步要加–outresult.pkl&#xff0c;才能计算准确率和召回率 python tools/test.py configs/fcos/fcosrddweed3.py work_dirs/fcosrddweed3/epoch_300.pth --outresultfcos.pkl3、计算准确率和召回率…