JOOQ 多集抛出语法异常

JOOQ multiset throwing syntax exception

最近转移到 JOOQ 3.15.5 并尝试了 Multiset 功能,但它正在抛出 SQLSyntaxErrorException。下面是我写的查询:

dslContext.select(
    tableA.asterisk(),
    multiset(
            select(tableB.DELETED, tableB.VALUE)
                .from(tableB)
                .where(tableB.ORDER_ID.eq(tableA.ORDER_ID))
    ).as("bookingAdditions")
).from(tableA)
 .where(tableA.BATCH_ID.greaterThan(batchId))
 .fetchInto(BookingDto.class);

关系如下:

|tableA|  1           n  |tableB| 
|      | --------------> |      | 
|      |                 |      | 
--------                  --------
(tableA)                  (tableB) 

这是 JOOQ 生成的查询:

set @t = @@group_concat_max_len; set @@group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array(`v0`, `v1`) separator ','), ']')), json_array()) from (select `tableb`.`deleted` as `v0`, `tableb`.`value` as `v1` from `db_name`.`booking_additions` as `tableb` where `tableb`.`order_id` = `tablea`.`order_id`) as `t`) as `bookingadditions` from `db_name`.`booking` as `tablea` where `tablea`.`batch_id` > 0; set @@group_concat_max_len = @t;

以下是例外情况:

org.jooq.exception.DataAccessException: SQL [set @t = @@group_concat_max_len; set @@group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array(`v0`, `v1`) separator ','), ']')), json_array()) from (select `tableb`.`deleted` as `v0`, `tableb`.`value` as `v1` from `db_name`.`booking_additions` as `tableb` where `tableb`.`order_id` = `tablea`.`order_id`) as `t`) as `bookingadditions` from `db_name`.`booking` as `tablea` where `tablea`.`batch_id` > ?; set @@group_concat_max_len = @t;]; You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'set @@group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(jso' at line 1
    at org.jooq_3.15.5.MYSQL.debug(Unknown Source)
    at org.jooq.impl.Tools.translate(Tools.java:2988)
    at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:639)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
    at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:295)
    at org.jooq.impl.AbstractResultQuery.fetchLazyNonAutoClosing(AbstractResultQuery.java:316)
    at org.jooq.impl.SelectImpl.fetchLazyNonAutoClosing(SelectImpl.java:2866)
    at org.jooq.impl.ResultQueryTrait.collect(ResultQueryTrait.java:357)
    at org.jooq.impl.ResultQueryTrait.fetchInto(ResultQueryTrait.java:1423)
    at com.company.BookingDAO.fetchBookings(BookingDAO.java:118)
    at

我正在使用 Mysql: 5.7。我究竟做错了什么?有什么提示吗?

当您在查询中使用 GROUP_CONCAT() 时,

jOOQ 生成三个用分号分隔的 SQL 语句。不幸的是,MySQL 的默认行为是不允许在单个请求中进行多个查询。

您必须更改 JDBC 连接选项以包括 allowMultiQueries

在此处阅读更多相关信息:https://blog.jooq.org/mysqls-allowmultiqueries-flag-with-jdbc-and-jooq/

关于多重陈述

除了所说的之外,您还可以将Settings.renderGroupConcatMaxLenSessionVariable指定为false并为您的会话或您自己的服务器增加服务器的@@group_concat_max_len变量.

jOOQ 在这里的默认设置是假设添加 JDBC 连接标志比更改服务器设置更容易,但这两种方法都是可行的。

关于相关派生表

此特定仿真需要支持相关派生表,MySQL 5.7 不支持,请参阅 https://github.com/jOOQ/jOOQ/issues/12045. You're not going to get a correlated MULTISET expression to work on MySQL 5.7, but you could write an almost equivalent MULTISET_AGG 表达式,如下所示:

dslContext.select(
    tableA.asterisk(),
    multisetAgg(tableB.DELETED, tableB.VALUE).as("bookingAdditions")
).from(tableA)
 .join(tableB).on(tableB.ORDER_ID.eq(tableA.ORDER_ID))
 .where(tableA.BATCH_ID.greaterThan(batchId))
 // You can group by the primary key, or tableA.fields() if you don't have a PK
 .groupBy(tableA.ID)
 .fetchInto(BookingDto.class);

MULTISET 不同,MULTISET_AGG 生成 NULL 值而不是空列表,以防您加入 tableB,这与 SQL 一样聚合函数。然后,您可以使用 coalesce(multisetAgg(...), multiset(...)) 作为解决方法。