You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jOOQ反应式transactionResult中setLocal无法设置PostgreSQL本地变量问题

问题:jOOQ反应式事务中setLocal设置PostgreSQL本地变量不生效

我尝试在jOOQ的dslContext.transactionResult中通过反应式方式为PostgreSQL设置本地变量,借助触发器将修改product表的用户ID(user_id)存入product history表。

触发器函数通过以下脚本获取user_id变量:

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

我希望通过jOOQ反应式事务复现如下SQL的行为:

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

但以下jOOQ代码无法生效,product history表中无法获取到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)));
  });
}

预期保存product记录时,user_id本地变量会被设置并写入product history表,但实际仅成功保存product记录,user_id未被存入。非反应式的dslContext.transaction功能正常,product history表可以获取到user_id变量,请问jOOQ是否支持反应式setLocal?

环境信息

  • jOOQ版本:3.16.5
  • 数据库:PostgreSQL 11.18 on x86_64-pc-linux-musl,64位
  • Java版本:17
  • 操作系统:macOS Big Sur [Version 11.6]
  • JDBC驱动:org.postgresql:postgresql:42.3.6

解决方案

jOOQ 3.16.x版本的反应式API中,setLocal方法存在上下文绑定问题,无法将本地变量正确关联到当前反应式事务的连接上,这就是非反应式事务正常但反应式场景失效的原因。可以通过以下两种方式解决:

  1. 直接执行SET LOCAL SQL语句替代setLocal方法
    把ctx.setLocal(...)替换为直接执行原生SQL,确保变量设置在当前事务的连接上下文里:

    public Mono<Product> upsertProduct(Long productId, String name, String userId) {
      return dslContext.transactionResult(configuration -> {
        DSLContext ctx = DSL.using(configuration);
        return Mono.from(ctx.execute("SET LOCAL user_id = ?", 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)));
      });
    }
    
  2. 升级jOOQ版本到3.17及以上
    jOOQ在3.17版本修复了反应式事务中setLocal的上下文绑定问题,升级后原代码的ctx.setLocal调用可以正常生效,无需修改逻辑。


内容的提问来源于stack exchange,提问作者Özlem Ulağ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:43:42