使用 JOOQ DSLContext.transactionResult 和 setLocal

问题描述 投票:0回答:1

我试图通过在 dslContext.transactionResult 中使用反应方式在 Postgresql 上设置局部变量。 我想在触发器的帮助下在产品历史表中保留 user_id,即更改产品表的用户的 ID。

我的产品历史表触发函数在其中使用这个脚本来获取 user_id 变量。

DECLARE user_id text := current_setting('user_id', true);

实际上我想通过使用 jooq 反应式事务支持来创建与此 sql 脚本相同的行为。

BEGIN;
SET LOCAL user_id = 'XXXXXXXXX';
insert into .....
COMMIT;

但是下面的 jooq 代码不起作用,user_id 变量没有在产品历史表中获取它的值。

  public Mono<Product> upsertProduct(Long productId, String name, String userId) {
    return dslContext.transactionResult(configuration -> {
      DSLContext ctx = DSL.using(configuration);
      return Mono.from(ctx.setLocal(DSL.name("user_id"), DSL.value(userId)))
                 .flatMap(result -> Mono.from(ctx.insertInto(PRODUCT)
                                                 .set(PRODUCT.ID, productId)
                                                 .set(PRODUCT.NAME, name)
                                                 .onConflictOnConstraint(Keys.PRODUCT_PK)
                                                 .doUpdate()
                                                 .set(PRODUCT.NAME, name)
                                                 .returning())
                                        .map(dbRecord -> dbRecord.into(Product.class)));
    });
  }

我预计它应该在产品历史表中设置局部变量 user_id,同时将产品记录保存到产品表中。但它没有设置局部变量,所以即使它将产品记录保存到产品表中,我也看不到产品历史表中的 user_id 字段。

请问一下setLocal的reactive是否支持?因为当我尝试通过使用 dslContext.transaction 来使用非反应性方式时..它有效并且我可以在产品历史表上看到局部变量。

jOOQ版本

3.16.5

数据库产品及版本

x86_64-pc-linux-musl 上的 PostgreSQL 11.18,由 gcc 编译(Alpine 12.2.1_git20220924-r4)12.2.1 20220924,64 位

Java 版本

17

操作系统版本

macOS Big Sur [版本 11.6]

JDBC 驱动名称和版本

org.postgresql:postgresql:42.3.6

jooq r2dbc
1个回答
1
投票

关于R2DBC的设计

根据底层

Result::getRowsUpdated
的 R2DBC 规范,不返回任何更新计数的查询根本不返回任何内容:

返回对数据库的查询更新的行数。如果查询没有更新任何行,则可能为空。

这与 JDBC 不同,在 JDBC 中,

Statement::executeUpdate
总是返回一个
int
值,例如
0
,就算一无所获

事实上,当您通过

Statement::execute
在流模式下使用 JDBC 时,它也不会为语句批处理中的每个语句返回更新计数,以防您发送多个
;
分隔的语句到服务器,例如在 MySQL 或 SQL Server 中。

现在,jOOQ 没有做任何特别的事情。它只是在这里继承了 R2DBC 的行为。如果 R2DBC

Statement
没有产生任何结果,那么 jOOQ 的
RowCountQuery

也不能

这对您的查询有何影响

您查询中的问题是您正在使用

flatMap()

Mono.from(ctx.setLocal(DSL.name("user_id"), DSL.value(userId)))
    .flatMap(result -> Mono.from(ctx.insertInto(PRODUCT) // ...

但是第一个查询不会产生任何结果,所以您的

flatMap()
lambda 永远不会被调用!你应该做的是使用
then()

Mono.from(ctx.setLocal(DSL.name("user_id"), DSL.value(userId)))
    .then(Mono.from(ctx.insertInto(PRODUCT) // ...
© www.soinside.com 2019 - 2024. All rights reserved.