首页 > 数据库 >一种失传已久的 SQL 多表连接查询,你从来没有见过的独门写法。

一种失传已久的 SQL 多表连接查询,你从来没有见过的独门写法。

时间:2024-10-16 18:49:46浏览次数:3  
标签:失传已久 多表 name private ROLE user SQL id USER

阅读本文之前,请投票支持这款 全新设计的脚手架 ,让 Java 再次伟大!

从 Left Join 说起

假设你有这样一个 n2n 的关系表,代表用户和角色之间的关系。

在这里插入图片描述

通常通过 left join 去连接这三张表,来查询出用户及其角色的信息。

SELECT 
    u.id AS user_id,
    u.name AS user_name,
    r.name AS role_name
FROM 
    "user" u
LEFT JOIN 
    "user_role_map" urm ON u.id = urm.user_id
LEFT JOIN 
    "role" r ON urm.role_id = r.id;
user_iduser_namerole_name
1AliceAdmin
1AliceUser
2BobUser
3CharlieGuest

查询出的结果中,Alice 这个用户出现了两次。这是显而易见的,因为这是一个 “Flatten” 的结果。

这样的结果是无法返回给客户端直接使用的。你需要进行处理,把重复的用户归纳到一起以后再返回给客户端进行展示,比如像下面这样:

user_iduser_nameuser’s_role_array备注
1Alice[(Admin),(User<List>),(Vip<List>),…(n)]试想任意节点都可能嵌套高度为 n 的子树的情况,各节点需直接返回 List<Map> 的形式供前端在 html 的 <li></li><select></select> 节点中展示。
2BobUser
3CharlieGuest

不幸的是这样的处理非常麻烦,你 join 的表越多这个代码越不好写,不相信你可以试试。

Group_contact

看到这里,你可能会觉得 agg_string 和 group_contact 等聚合函数一定程度上能实现这个需求。但是聚合函数人如其名,作用为「聚合」。

回到上面的例子,不要局限于例子中树的高度,试想任意节点都可能嵌套一颗高度为 n 的子树,并且你的业务逻辑还需要对子树的节点做数据结构的转换。显然,字符串的「聚合」在解决这样复杂树结构的问题时显得力量不足。

这样的复杂树结构是否很常见?不,它不常见,但是它也不少见。因为除了互联网,还有很多行业也在使用数据库支撑他们的业务。

谈谈 ORM

有没有方便的方法来获取这个「嵌套」的结果呢?使用 Hibernate 这样的 ORM 框架是个不错的主意:

@Entity
public class User {
    @Id
    private int id;

    @Column(name = "name", nullable = false)
    private String name;

    @ManyToMany
    @JoinTable(
        name = "user_role_map",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles;
}

@Entity
public class Role {
    @Id
    private int id;

    @Column(name = "name", nullable = false)
    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
}

Hibernate 直接帮你把数据库的结果映射到了嵌套结果集中。现在你可以直接把 List<User> 返回给客户端了,因为这个结果现在展示为:

user_iduser_nameuser’s_role_array备注
1Alice[(Admin),(User<List>),(Vip<List>),…(n)]无论树的形状和高度,Hibernate 把各节直接映射为 List<Map> 的形式供前端在 html 的 <li></li><select></select> 节点中展示。
2BobUser
3CharlieGuest

Hibernate 的问题

使用 Hibernate 的代价就是你的心智负担很大。除了要学习很多注解以外,还有很多夸张的概念需要深入理解,才能够写出能正常运行的代码。

那么,有没有一种简单的方法,可以通过 SQL 的方式,直接查询出这种嵌套的结果集, 然后扔给客户端进行处理呢?答案是有的。

全新的解决方案

public static void main(String[] args) {
        UserRoleEntity userRoleEntity = select(
                USER.ID,
                USER.NAME,
                array(select(ROLE.ID, ROLE.NAME)
                        .from(ROLE)
                        .join(USER_ROLE_MAP).on(ROLE.ID.eq(USER_ROLE_MAP.ROLE_ID))
                        .where(USER_ROLE_MAP.USER_ID.eq(USER.ID))
                ).as("roles")
        ).from(USER);
        System.out.println(userRoleEntity);
    }


class UserRoleEntity {
    private Long id;
    private String name;
    private List<Role> roles;
}

是的,如你所见,通过在 Java 的 main 方法里面用 Java 语言来编写「类型安全的 SQL」并通过 Array 方法一键转换为嵌套对象,免去了学习 Hibernate 的烦恼。

什么样的 Java 框架可以实现这样的功能?点击下方链接获取详情

标签:失传已久,多表,name,private,ROLE,user,SQL,id,USER
From: https://blog.csdn.net/ccmjga/article/details/142908946

相关文章

  • Elasticsearch与MySQL的概念对比
    我们统一的把mysql与elasticsearch的概念做一下对比:MySQLElasticsearch说明TableIndex索引(index),就是文档的集合,类似数据库的表(table)RowDocument文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式ColumnFiled字段(Field),就是JSON文......
  • jeecgboot 3.7.1 一键将生成好的代码复制到前后端项目目录,并执行SQL插入菜单的python
    importshutilimportosimportmysql.connectorfrommysql.connectorimportErrorbase_dir="D:/pro/JeecgBoot-v3.7.1"code_dir="/gendcode"package_name="meetrice"#MySQL连接配置config={'user':'root......
  • 关系型数据库(mysql/InnoDB)的前世今生
    博主专注于Java程序开发,旨在与各路大神做技术交流,觉得不错的朋友,点个关注,有想深度交流,也可参考博主其他文章:java知识体系搭建-CSDN博客前言本文将汇总介绍关系型数据库的常用知识,理论偏多,希望大家都能对关系型数据库有个总体的认识。具体应用,大家需要在工作中自行融汇。介绍......
  • my2sql数据闪回
    使用限制只能回滚DML,不能回滚DDL使用回滚/闪回功能时,binlog格式必须为row,且binlog_row_image=full,DML统计以及大事务分析不受影响MySQL8.0版本需要在配置文件中加入default_authentication_plugin=mysql_native_password,用户密码认证必须是mysql_native_password才能解析......
  • 高可用 proxysql + mysql MGR
    MGR配置安装系统:centos7.9yuminstallhttps://repo.percona.com/yum/percona-release-latest.noarch.rpmpercona-releaseenable-onlyps-8x-innovationreleasepercona-releaseenabletoolsreleaseyuminstallpercona-server-server第一台机器配置#mgr#basic......
  • 倒排索引及ES相关概念对比MySQL
    一、倒排索引1、先把文档内容进行分词,形成词条与文档ID的对应关系,叫做词条库,词条具备唯一性,建立索引2、对搜索内容进行分词,分词后得到一个关键词列表,根据关键词去词条库中匹配,在找对应的文档ID列表3、然后根据文档ID列表,找到对应的文档信息对比:   二、ES相关概念对比My......
  • SqlUtils 使用
    一、前言随着Solon3.0版本发布,新添加的SqlUtils接口,用于操作数据库,SqlUtils是对Jdbc原始接口的封装。适合SQL极少或较复杂,或者ORM不适合的场景使用。二、SqlUtils使用1、引入依赖<dependency><groupId>org.noear</groupId><artifactId>solon-data-sq......
  • Elasticsearch相关概念对比mysql
    一、简介ElasticSearch是强大的搜索和分析引擎。能快速存储、检索和处理大量数据,提供实时搜索结果,擅长处理复杂查询,助力企业从海量数据中获取有价值信息,优化业务决策和提升用户体验。二、术语2.1索引Elasticsearch中的索引类似MySQL中的表,是相同类型文档的集合。它如同表......
  • 5大主流方案对比:MySQL千亿级数据线上平滑扩容实战
    在项目初期,我们部署了三个数据库A、B、C,此时数据库的规模可以满足我们的业务需求。为了将数据做到平均分配,我们在Service服务层使用uid%3进行取模分片,从而将数据平均分配到三个数据库中。如图所示:图片后期随着用户量的增加,用户产生的数据信息被源源不断的添加到数据库中......
  • Windows安装MySQL(zip安装)
    1.下载#dev.mysql.com>Download>下载MySQLCommunity(GPL)Downloads2.配置my.ini[mysqld]#一定要加这个,默认启动端口是3306,一般不会用默认端口port=50013#设置mysql的安装目录,一定要\\,否则不识别basedir=G:\\soft\\mysql-8.4.3-winx64#设置mysql数据库的数据的......