使用 jooq 在 hstore 合并的重复键上

On duplicate key with hstore merge using jooq

目前,我正在尝试在 jooq 中实现以下 sql 查询:

INSERT INTO table as t (id, hstore_data) 
VALUES ('test', '"key1" => "val1"') 
ON CONFLICT (id) 
DO UPDATE SET hstore_data = add(t.hstore_data, '"keyX" => "valX"');

add()是一个自定义函数:

CREATE FUNCTION add(hstore, hstore) RETURNS hstore
AS 'select  || ;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;

到目前为止,我设法解决了这个问题 运行:

return DSL.using(configuration)
            .insertInto(TABLE)
            .columns(TABLE.ID, TABLE.HSTORE_DATA)
            .values(table.getId(), table.getHstoreData())
            .onDuplicateKeyUpdate()
            .set(TABLE.HSTORE_DATA,
                            merge(
                                    DSL.using(configuration).select(TABLE.HSTORE_DATA).from(TABLE).where(TABLE.ID.eq(table.getId())).fetchAnyInto(HashMap.class)
                                    , table.getHstoreData()

                            )
                    )
            .execute();

merge() 是一个合并两个地图的简单 JAVA 函数。

这种方法有效。但是,我想按照第一个查询的建议在数据库服务器上进行所有处理。

我尝试使用 jooq 为 add() 生成的例程。但似乎 jooq 不使用 hstore 绑定。绑定在 ConfigGenerator 中定义如下:

types.add(new ForcedType()
            .withUserType("java.util.Map<String, String>")
            .withBinding("HStoreStringBinding")
            .withIncludeExpression(".*_data")
            .withIncludeTypes(".*"));
types.add(new ForcedType()
            .withUserType("java.util.Map<String, Long>")
            .withBinding("HStoreLongBinding")
            .withIncludeExpression(".*_counts")
            .withIncludeTypes(".*"));

绑定适用于 hstores,但不适用于自定义函数。

  1. 有没有更聪明的方法?
  2. add() 未正确输入的原因可能是什么?
  3. 如何告诉 jooq 在合并中使用原始值,就像我在使用 t.hstore_data 的原始 SQL 查询中所做的那样?

What might be the reason for add() not being correctly typed?

尝试命名您的函数参数,否则您无法将它们与 includeExpression 属性 匹配。要匹配函数的 return 值,请将函数名称本身用作 includeExpression。当然,您可以只留下 属性,并使用更通用的绑定匹配所有 hstore 类型:

types.add(new ForcedType()
            .withUserType("java.util.Map<String, String>")
            .withBinding("HStoreStringBinding")
            .withIncludeTypes("hstore"));

How can I tell jooq to use the original value in the merge as I do in the raw SQL query with t.hstore_data?

代码生成成功后,您只需使用添加函数,就像在 SQL 版本的语句中一样:

set(TABLE.HSTORE_DATA, Routines.add(TABLE.HSTORE_DATA, table.getHstoreData()))