代码之家  ›  专栏  ›  技术社区  ›  DWilches

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

  •  2
  • DWilches  · 技术社区  · 7 年前

    我试图使用jOOQ创建一个类似于 arrayRemove 但这允许一次从类型为的PostgreSQL列中删除多个元素 uuid[]

    所以我的第一次尝试是:

    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 而不是一个空数组,如果我尝试删除每个元素。

    因此,我在代码中添加了一个合并,使其返回一个空数组:

    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中的bug吗?

    2 回复  |  直到 7 年前
        1
  •  2
  •   DWilches    7 年前

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

    还可以查看Lukas Eder关于如何使用 领域

    最后一段代码(带有泛型)如下所示:

    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();
    
        2
  •  1
  •   Lukas Eder    7 年前

    你的 field("{}") 不会生成 {} 字符串,但被认为是jOOQ的普通SQL模板语言的一部分,不幸的是,它不允许转义这些大括号: https://www.jooq.org/doc/latest/manual/sql-building/plain-sql-templating

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

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