【问题标题】:GraphQL Java: Grouping SQL and MappingGraphQL Java:分组 SQL 和映射
【发布时间】:2020-08-08 01:39:01
【问题描述】:

我正在构建 graphql-java 春季启动应用程序。 假设我有这个架构:

type Foo {
id: ID! name: String bars: [Bar]
}
type Bar {
id: ID! name: String
}
query{
  foo(arg: String): [Foo]
}

在 BE 上,我正在使用 JOOQ pojos。

目前所有的 Foo 都被获取,然后对于每个 foo,所有的 Bars 都被另一个查询获取。 我想用一个查询来做到这一点:

select * from foo 
left join bar on foo.id = bar.foo_id;

您知道如何实现这一目标吗?我是 GraphQL 的真正新手。

技术栈: 弹簧靴 JOOQ graphql-java graphql-java-tools

【问题讨论】:

    标签: spring-boot graphql jooq graphql-java


    【解决方案1】:

    嵌套集合的经典 SQL 策略

    在您的简单示例中,LEFT JOIN 绝对是一个选项。这就是 JPA/Hibernate 等 ORM 在获取嵌套集合时在幕后所做的事情。该策略有一些缺点:

    • 存在数据重复。对于每个BAR(子表),您将复制匹配的FOO(父表)的数据。这可能会导致通过网络传输大量开销。您需要的连接越多(即嵌套越多),这种情况就会变得越来越糟
    • 有笛卡尔积。如果您想一次性完成,您不能嵌套多个集合而不在子表之间生成笛卡尔积。对于笛卡尔积,很难“记住”哪些组合实际上是合法的,哪些是连接树的产物。因此,您将返回运行多个查询,每个嵌套树分支一个

    使用标准 SQL JSON

    但是,从 jOOQ 3.14 开始,有一个更好的方法。您可以使用 XML 或 JSON,具体取决于您使用的数据库方言。这里的关键特性是 XMLAGGJSON_ARRAYAGG,它们允许将数据聚合到 XML 元素或 JSON 对象中。由于您将使用 GraphQL 生成 JSON 文档,我猜您将使用 JSON。

    使用标准 SQL(例如由 Oracle 实现),您为示例生成的 SQL 查询可能如下所示:

    SELECT
      JSON_ARRAYAGG(
        JSON_OBJECT(
          KEY "id" VALUE foo.id,
          KEY "name" VALUE foo.name,
          KEY "bars" VALUE (
            SELECT 
              JSON_ARRAYAGG(
                JSON_OBJECT(
                  KEY "id" VALUE bar.id,
                  KEY "name" VALUE bar.name
                )
              )
            FROM bar
            WHERE bar.foo_id = foo.id
          )
        )
      )
    FROM foo
    

    就目前而言,这些方言应该能够支持 jsonArrayAgg()jsonObject()(或其模拟,例如在 PostgreSQL 中):

    • 蟑螂数据库
    • DB2 LUW 11+
    • H2
    • MariaDB 10.2+
    • MySQL 5.7+
    • Oracle 12c+
    • PostgreSQL

    More details in this blog post.

    将来也可能使用FOR JSON 在 SQL Server 中进行模拟。

    请注意,JSON_ARRAYAGG() 将空集聚合到 NULL,而不是空集 []If that's a problem, use COALESCE()

    开箱即用的解决方案

    事实上,我以前就想到过要开箱即用地提供这个。我们可能会在不久的将来这样做:https://github.com/jOOQ/jOOQ/issues/10122

    【讨论】:

    • 这非常有效。当然,我的模型有点复杂,但该策略非常适用。尤其是与 PostgreSQL 的横向连接结合使用时。
    • @K.Kostadinov:您是否已经在尝试使用 jOOQ 3.14?
    • @Lucas Eder:不,还没有,我还在用 3.13.1,你有什么特别的想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2018-09-10
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    • 2017-02-28
    相关资源
    最近更新 更多