使用jOOQ从Postgres数组中删除多个元素

时间:2018-05-03 16:46:52

标签: postgresql jooq

我尝试使用jOOQ创建类似于arrayRemove的函数,但允许从uuid[]类型的PostgreSQL列中一次删除多个元素。

所以我的第一次尝试是:

private Field<UUID[]> arrayRemoveAll(final Field<UUID[]> field, final Set<UUID> elements) {
    return select(field("array_agg(tab.col)", UUID[].class))
            .from(unnest(field).as("tab", "col"))
            .where(field("tab.col", UUID.class).notIn(elements))
            .asField();
}

成功删除每个请求的元素,但如果我尝试删除每个元素,则会出现返回null而不是空数组的问题。

所以我在我的代码中添加了一个coalesce,使它返回一个空数组:

private Field<UUID[]> arrayRemoveAll(final Field<UUID[]> field, final Set<UUID> elements) {
    final Field<UUID[]> newArray = select(field("array_agg(tab.col)", UUID[].class))
            .from(unnest(field).as("tab", "col"))
            .where(field("tab.col", UUID.class).notIn(elements))
            .asField();
    return coalesce(newArray, field("{}", UUID[].class));
}

但是运行此代码会抛出此异常:

org.jooq.exception.DataAccessException: SQL [<<confidential SQL removed>>]
    Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"

这是它抱怨的SQL异常的一部分(注意尾随的逗号和coalesce中缺少第二个参数):

coalesce((select array_agg(tab.col)
          from unnest("my_schema"."my_table"."my_field") as "tab"("col")
          where tab.col not in (?, ?)), )

这是jOOQ中的错误吗?

2 个答案:

答案 0 :(得分:2)

我发现上面的代码中混合了fieldval,将field("{}", UUID[].class)更改为val(new UUID[0])可以解决问题。

另请查看Lukas Eder关于如何使用field解决问题的答案。

所以带有泛型的最终代码看起来像这样:

private <T> Field<T[]> arrayRemoveAll(final Field<T[]> field, final Set<T> elements, final T[] emptyArray) {
    final Field<T[]> newArray = select(field("array_agg(tab.col)"))
            .from(unnest(field).as("tab", "col"))
            .where(field("tab.col").notIn(elements))
            .asField();
    return coalesce(newArray, val(emptyArray));
}

你可以在你的陈述中使用它:

using(configuration)
    .update(MY_TABLE)
    .set(MY_TABLE.MY_COLUMN,
         arrayRemoveAll(MY_TABLE.MY_COLUMN, someElements, new UUID[0]))
    .where(MY_TABLE.ID.eq(...))
    .execute();

答案 1 :(得分:1)

你的field("{}")没有在SQL中生成{}字符串,但被认为是jOOQ的纯SQL模板语言的一部分,遗憾的是它不允许转义那些括号: https://www.jooq.org/doc/latest/manual/sql-building/plain-sql-templating

幸运的是,PostgreSQL支持更正式,符合标准的方法来创建一个空数组文字:

field("array[]::uuid[]", UUID.class)