java jOOQ多集运算符在查询时返回嵌套的JsonArray

q8l4jmvw  于 2023-03-11  发布在  Java
关注(0)|答案(2)|浏览(131)

对于上下文,我们在Quarkus中使用jooq 3.17和vertx-jooq 6.5.5。因此,所有内容都是Mutiny流。我们不能使用阻塞操作(如fetch())。
正如the official tutorial中所建议的,我们尝试使用jOOQ Multiset Operator,为此,我们使用了以下代码:

ReactiveMutinyQueryExecutor executor = ...

executor
        .query(dslContext -> dslContext
            .select(TABLE_A.TABLE_C_ID,
                TABLE_C.NAME,
                DSL
                    .multiset(DSL
                        .select(TABLE_B.TABLE_C_ID, TABLE_B.NAME, TABLE_B.PARAMETER_TYPE)
                        .from(TABLE_B)
                        .where(TABLE_B.TABLE_A_ID.eq(TABLE_A.TABLE_A_ID)))
                    .as(TABLE_BS))
            .from(TABLE_A)
            .join(TABLE_C)
            .using(TABLE_C.TABLE_C_ID)
            .where(TABLE_A.TABLE_C_ID.eq(tableCId)))
        .map(queryResult -> queryResult.get(TABLE_BS, MyPojo.class))

调用get时发生异常:
org.jooq.exception.DataTypeException:无法从[[8,“a”,“NUMBER”],[9,“b”,“NUMBER”]](类io.vertx.core.json.jsonArray)转换为类com.MyPojo
我们的目标是将多重集Map到MyPojo。

.convertFrom(MyClass::toMyPojo));

建议的convertFrom()方法没有任何效果,我们不调用fetch(如上所述)。
但是,调用queryResult.get(TABLE_BS, String.class)时,结果是嵌套的JSONArray:

[[8,"a","NUMBER"],[9,"b","NUMBER"]]

我们希望在这里至少接收一个嵌套的JsonObject,所以在我们的示例中,JsonArray中有两个JsonObject。

6ovsh4lw

6ovsh4lw1#

从我的Angular 来看,集成到流框架(例如Akka StreamsSmallRye Mutiny [在Quarkus中使用],Vert.x)是必不可少的。
所用类型(如:Uni、Multi用于SmallRye Mutiny)
与JDK标准类型(如CompletionStage)不同。转换是可能的,但并不总是有用的。多行的流可以转换为包含所有元素列表的完成阶段。For CompletionStage是一个可用于创建SmallRye Multi的转换器。但是流是无用的,因为结果已经可用。2因此流必须被直接填充(没有这样的转换)来利用流的优点(如延迟计算和减少内存消耗)。
vertex-jooq等第三方库填补了差距。

byqmnocz

byqmnocz2#

直接使用jOOQ执行

jOOQ博客上的这篇文章解释了why you should execute jOOQ queries with jOOQ,而不是第三方。原因之一是类型安全的MULTISET(和ROW)反序列化依赖于jOOQ实现的内部SQL/JSON序列化格式的知识。jOOQ在JDBC(阻塞)或R2 DBC(非阻塞)上支持这种开箱即用的反序列化。

使用内部API将JSON转换为Result

您可以使用jOOQ的内部API将JSON数据结构转换为org.jooq.Result,然后可以使用它将嵌套记录结构转换为您自己的MyPojo类型。鉴于这是关于内部API的,我无法在Stack Overflow上说明这是如何工作的,因为答案可能在一个月后就过时了。
但是您可以让它工作,甚至可以在您可能正在使用的第三方vert.x-to-jOOQ桥中实现它。
在任何情况下,都有一个未决的特性请求,要求将此功能作为公共API提供:#12012,因此未来的第三方也可以提供此功能。

为什么是数组的数组?

首选序列化格式使用数组的数组而不是对象的数组有多种原因,包括:

  • 它不那么冗长,因此数据传输也更少(每行都有冗余!)
  • 按索引访问列也比按字符串访问列快
  • 列名可能不明确(例如SELECT 1 AS a, 2 AS a, t.a FROM t),因此无论如何都不可靠

请注意,确切的序列化格式没有文档记录,因此它可能会在不同版本之间发生变化,例如,当RDBMS的SQL/JSON支持有限制时。此外,在某些方言中,不可能以这种方式序列化JSON数组(例如,由于bug或限制),因此jOOQ生成具有伪键名的对象数组,如[{"v1":1,"v2":2}]
请参见this article on the sobering parts of trying to standardise on SQL/JSON support across RDBMS了解一些背景知识。

相关问题