For context, we are using jooq 3.17 and vertx-jooq 6.5.5 inside Quarkus. As a consequence, everything is a Mutiny stream. We cannot use blocking operations (like fetch()
).
As proposed in the official tutorial, we tried to utilize the jOOQ Multiset Operator. For that, we are using the flowing code:
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))
When calling get
an exception occurs:
org.jooq.exception.DataTypeException: Cannot convert from [[8,"a","NUMBER"],[9,"b","NUMBER"]] (class io.vertx.core.json.JsonArray) to class com.MyPojo
Our goal is to map the multiset to a MyPojo.
.convertFrom(MyClass::toMyPojo));
The suggested convertFrom()
method does not have any effect, we don't call fetch (as stated above).
However, when calling queryResult.get(TABLE_BS, String.class)
, the result is a nested JSONArray:
[[8,"a","NUMBER"],[9,"b","NUMBER"]]
where we were hoping to receive at least a nested JsonObject. So in our example two JsonObjects inside a JsonArray.
This article on the jOOQ blog explains why you should execute jOOQ queries with jOOQ, not with third parties. One of the reasons is that the type safe MULTISET
(and ROW
) deserialisation relies on knowledge about the internal SQL/JSON serialisation format implemented by jOOQ. jOOQ supports this deserialisation out of the box on JDBC (blocking) or R2DBC (non-blocking).
Result
You could use internal API from jOOQ to convert the JSON data structure to a org.jooq.Result
, which can then be used to transform the nested record structure to your own MyPojo
types. Given that this is about internal APIs, I cannot say how this works here on Stack Overflow, as the answer might be outdated already in a month.
But you could get it to work, or even implement it in that third party vert.x-to-jOOQ bridge that you're probably using.
In any case, there's a pending feature request to offer this functionality as public API: #12012, so future third parties can offer this functionality as well.
There are various reasons why the preferred serialisation format uses arrays of arrays, rather than arrays of objects, including:
SELECT 1 AS a, 2 AS a, t.a FROM t
), so it's not reliable anywayNote that the exact serialisation format isn't documented, so it might change as well between releases, e.g. when there's a limitation in the SQL/JSON support of an RDBMS. Additionally, in some dialects, it's not possible to serialise JSON arrays this way (e.g. due to bugs or limitations), so jOOQ generates arrays of objects with dummy key names, such as [{"v1":1,"v2":2}]
. Also not documented.
See this article on the sobering parts of trying to standardise on SQL/JSON support across RDBMS for some background.