如何在 jOOQ 中转换 "to_json()" PostgreSQL 函数?

问题描述 投票:1回答:1

我正试图将以下PostgreSQL查询转换为jOOQ,但似乎找不到合适的方法来解决这个问题。下面是这个查询。

SELECT b.book_id AS b_id, b.title, b.price, b.amount, b.is_deleted,
to_json(array_agg(DISTINCT aut.*)) as authors, 
to_json(array_agg(DISTINCT cat.*)) as categories 
FROM book b 
LEFT JOIN author_book AS ab ON b.book_id = ab.book_id
LEFT JOIN author AS aut ON ab.author_id = aut.author_id
LEFT JOIN category_book AS cb ON b.book_id = cb.book_id
LEFT JOIN category AS cat ON cb.category_id = cat.category_id
GROUP BY b_id ORDER BY b_id ASC;

到目前为止,我在jOOQ中得到的是这样的结果。

    dslContext
   .select(BOOK.BOOK_ID, BOOK.TITLE, BOOK.PRICE, BOOK.AMOUNT, BOOK.IS_DELETED, 
           DSL.val(DSL.jsonArray(DSL.arrayAggDistinct(AUTHOR.AUTHOR_ID), 
                                 DSL.arrayAggDistinct(AUTHOR.FIRST_NAME),
                                DSL.arrayAggDistinct(AUTHOR.LAST_NAME))
               ).cast(SQLDataType.JSON),                    
        DSL.val(DSL.jsonArray(DSL.arrayAggDistinct(CATEGORY.CATEGORY_ID), 
                              DSL.arrayAggDistinct(CATEGORY.NAME), 
                              DSL.arrayAggDistinct(CATEGORY.IS_DELETED))
            ).cast(SQLDataType.JSON)
    ).from(BOOK
            .leftJoin(AUTHOR_BOOK).on(BOOK.BOOK_ID.eq(AUTHOR_BOOK.BOOK_ID))
            .leftJoin(AUTHOR).on(AUTHOR_BOOK.AUTHOR_ID.eq(AUTHOR.AUTHOR_ID))
            .leftJoin(CATEGORY_BOOK).on(BOOK.BOOK_ID.eq(CATEGORY_BOOK.BOOK_ID))
            .leftJoin(CATEGORY).on(CATEGORY_BOOK.CATEGORY_ID.eq(CATEGORY.CATEGORY_ID))
    ).where(AUTHOR.AUTHOR_ID.eq(Long.valueOf(authorId))
    ).groupBy(BOOK.BOOK_ID).orderBy(BOOK.BOOK_ID.asc())

当我执行jOOQ代码时,我得到以下异常。

类型类 org.jooq.impl.JSONArray is not supported in dialect DEFAULT(方言)。

我上网查了一下这个例外,发现只有这个类似的例外在 这个 问题:有什么合适的方法解决PostgreSQL的转换问题吗?有没有合适的方法解决PostgreSQL的转换问题?to_json 在给定的aut(hor)cat(egory)表的所有字段上保持DISTINCT的函数和array_agg()组合?

UPDATE:这是我在jOOQ中用非类型安全的方式写查询的另一种方法。

dslContext.resultQuery(DBQueries.GET_ALL_BOOKS_BY_AUTHOR_ID, Long.valueOf(authorId)));

...这里是代码 DBQueries.GET_ALL_BOOKS_BY_AUTHOR_ID 变量。

public class DBQueries {
//...
static String GET_ALL_BOOKS_BY_AUTHOR_ID = "SELECT b.book_id AS b_id, b.title, b.price, b.amount, b.is_deleted, " +
            "to_json(array_agg(DISTINCT aut.*)) as authors, to_json(array_agg(DISTINCT cat.*)) as categories " +            
            "FROM book b " + 
            "LEFT JOIN author_book AS ab ON b.book_id = ab.book_id " +
            "LEFT JOIN author AS aut ON ab.author_id = aut.author_id " +
            "LEFT JOIN category_book AS cb ON b.book_id = cb.book_id " +
            "LEFT JOIN category AS cat ON cb.category_id = cat.category_id " +
            "WHERE aut.author_id = :id " + 
            "GROUP BY b_id ORDER BY b_id ASC;"; 
}

另外,我已经更新了我的问题,以便清楚我是如何使用 resultQuery() 方法来实现我想要的东西。我想知道如何在jOOQ中以尽可能多的类型安全的方式实现这个目标,因为我有一个更复杂的查询,我不知道是否可以通过不使用PostgreSQL来实现。to_json() 函数。例如,我想创建类似于 这个 在jOOQ中,像bytefish.de网站提交的链接中的 "04_create_functions.sql "一节一样。

get_image
--------------------------------------------------------------
 {"imageid" : 1, 
  "hash" : "a3b0c44", 
  "description" : "Some Description", 
  "created_on" : "2015-03-09T22:00:45.111", 
  "comments" : [{"commentid":1, "imageid":1, "text":"Awesome!", "createdon":"2015-03-09T22:58:47.783"},
                {"commentid":2, "imageid":1, "text":"This is just a second comment.", "createdon" : "2015-03-09T22:58:47.783"}], 
  "tags" : [{"tagid":1,"name":"Cool"}, 
            {"tagid":2,"name":"Berlin"}]}
(1 row)

我正试图为(book)order的report做同样的事情,其中查询涉及8张表(我没有在这里发布该查询,因为我试图在jOOQ中解决更简单的问题,即创建JsonArray)。

json postgresql aggregate jooq
1个回答
1
投票

你的具体错误

  • 你在包装一个 Field 表达式(DSL.jsonArray())在 DSL.val(),它是用于绑定值的。这样做是行不通的,也是导致你的异常的原因。
  • 但是,你还不能把一个普通的数组变成一个 JSON jOOQ不知道你这样做的意思是要调用 to_json 幕后。从jOOQ 3.13开始,你将不得不使用一些 纯SQL模板化 (见下面的例子),或者,你获取一个数组而不在你的SQL逻辑中把它变成JSON,只在你的Java客户端逻辑中把它变成JSON。

普通的SQL模板示例。

DSL.field("to_json({0})", JSON.class, DSL.arrayAggDistinct(AUTHOR.AUTHOR_ID))

jOOQ 3.14 JSON支持

请注意,jOOQ 3.14将支持 很多 通过标准的SQL JSON API以及SQL Server的 FOR JSON 条款。

而且。


1
投票

正如 @Lukas_Eder 所指出的,要解决这个问题,需要通过普通的 SQL templating 创建 JSON 对象,就像下面的例子。

DSL.field("to_json({0})", JSON.class, DSL.arrayAggDistinct(AUTHOR.AUTHOR_ID))

我在文档中阅读了更多关于上述方法的内容,并了解了如何根据自己的需要修改方法(为了与PostgreSQL语法中发布的方法相同)。

DSL.field( "to_json(array_agg(DISTINCT author.*))", JSON.class, DSL.arrayAgg(AUTHOR.AUTHOR_ID) ).as("authors")
© www.soinside.com 2019 - 2024. All rights reserved.