Java 如何转换;到“u json()”;jOOQ中的PostgreSQL函数?

Java 如何转换;到“u json()”;jOOQ中的PostgreSQL函数?,java,json,postgresql,aggregate,jooq,Java,Json,Postgresql,Aggregate,Jooq,我试图将下面的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

我试图将下面的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

我在谷歌上搜索了这个异常,只发现了这个类似的异常。有没有合适的解决办法来解决PostgreSQL
到_json
函数的转换,以及数组_agg()的组合,该数组在给定aut(hor)/cat(egory)表的所有字段上都是不同的

更新: 这是我用非类型安全的方式在jOOQ中编写查询的另一种方式:

dslContext.resultQuery(DBQueries.GET_ALL_BOOKS_BY_AUTHOR_ID, Long.valueOf(authorId)));
…下面是数据库查询的代码。按作者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)
我正在尝试为(图书)订单的报告做同样的事情,其中查询涉及8个表(我没有在这里发布该查询,因为我试图解决jOOQ中更简单的问题,即创建JsonArray)。

您的具体错误
  • 您正在将一个
    字段
    表达式(
    DSL.jsonArray()
    )包装到中,该表达式用于绑定值。这不起作用,这是您出现异常的原因
  • 但是,您还不能通过这种方式将普通数组包装成
    JSON
    数组。jOOQ不知道您的意思是在幕后调用
    到_json
    。从JOOQ3.13开始,您将不得不使用一些(参见下面的示例),或者,在SQL逻辑中获取数组而不将其转换为JSON,然后仅在Java客户机逻辑中将其转换为JSON
普通SQL模板示例:

DSL.field("to_json({0})", JSON.class, DSL.arrayAggDistinct(AUTHOR.AUTHOR_ID))
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
子句支持更多的JSON功能:

以及:


正如@Lukas_Eder指出的,要解决这个问题,需要通过简单的SQL模板创建JSON对象,如以下示例所示:

DSL.field("to_json({0})", JSON.class, DSL.arrayAggDistinct(AUTHOR.AUTHOR_ID))
我在文档中阅读了更多关于上述方法的内容,并了解了如何根据自己的需要修改该方法(以便与PostgreSQL语法中的有问题的方法相同):


如果我理解正确,您建议使用“普通SQL模板”来构建最终结果,方法是使用命名/内联参数,将作者和类别作为普通值数组,或者使用类似
resultQuery的内容​(String plainSQL,Object..bindings)
方法,在该方法中,我将一次性传递普通编写的SQL查询和(在本例中)authorId的值(用于执行搜索)(但这不是类型安全的方式)?我已更新了我的问题,以便更清楚地了解我试图实现的目标。@NikolaS:不,不是针对整个查询,就为了那个函数调用!我会更新我的answer@Lukas_Eder:我听取了您的建议,查阅了文档,并按照您的和文档示例调整了jOOQ代码。解决方案可以在我自己的答案中看到,如果您有任何建议/意见,请让我知道。再次感谢。:)@尼古拉斯:太好了,谢谢你在这里记录下你自己的解决方案,作为回答。人们应该经常这样做!在上一个示例中,您不需要传递
DSL.arrayAgg()
表达式,因为您没有任何模板占位符来匹配它(例如
{0}
)。但是,如果需要,您仍然可以传递
AUTHOR
表,例如
DSL.field(“to_json(array_agg(distinct{0}.*)”,json.class,AUTHOR)