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

Quarkus中Hibernate Reactive持久化实体遇Vert.x上下文报错求助

解决Quarkus中Hibernate Reactive的Vert.x上下文隔离错误

环境信息

  • Quarkus版本:2.11.1.Final
  • 核心依赖:
    • smallrye-mutiny-vertx-web-client
    • quarkus-resteasy-reactive
    • quarkus-hibernate-reactive

问题描述

在长REST流程中批量持久化实体时,触发如下错误:

当前操作需要一个安全(隔离的)Vert.x子上下文,但当前上下文未被标记为该类型。
您仍可使用Hibernate Reactive,只需避免使用隐式需要访问有状态上下文的方法,例如MutinySessionFactory#withTransaction和#withSession。

尝试过的代码

初始实现(报错)

@Inject
Mutiny.SessionFactory sf;

public Uni<List<T>> createAll(List<T> t) {
  if (LOGGER.isDebugEnabled()) {
    LOGGER.debug("#createAll(T)...  {}", t);
  }
    
  return sf.withTransaction(
      (s, t) -> s.persistAll((Object[]) t.toArray(new T[0]))
          .replaceWith(t));
}

修改为无状态事务(仍报错)

return sf.withStatelessTransaction((s, t) ->s.insertAll((Object[]) t.toArray(new T[0]))
    .replaceWith(t));

解决方案

1. 手动管理Session与事务,指定Worker线程池执行

由于withTransaction和withStatelessTransaction都依赖Quarkus的隔离上下文,当当前上下文不满足要求时,可手动创建Session、控制事务,并将操作切换到Worker线程池(天然具备隔离上下文):

@Inject
Mutiny.SessionFactory sessionFactory;
@Inject
Infrastructure infrastructure;

public Uni<List<T>> createAll(List<T> entities) {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("#createAll(T)...  {}", entities);
    }

    return sessionFactory.openSession()
            // 开启事务
            .onItem().invoke(session -> session.beginTransaction())
            // 执行持久化操作
            .onItem().transformToUni(session ->
                    session.persistAll(entities.toArray(new T[0]))
                            // 提交事务
                            .onItem().invoke(() -> session.getTransaction().commit())
                            // 失败时回滚
                            .onFailure().invoke(throwable -> session.getTransaction().rollback())
                            .replaceWith(entities)
            )
            // 无论成功失败都关闭Session
            .onTermination().invoke(session -> session.close())
            // 指定在Worker线程池执行,确保上下文隔离
            .runSubscriptionOn(infrastructure.getDefaultWorkerPool());
}

2. 检查REST流程上下文完整性

如果你的REST流程中存在Vert.x Web Client调用或自定义异步操作,需确保操作始终处于Quarkus的Reactive上下文内:

  • 避免在异步回调中脱离上下文执行持久化操作
  • 若使用Vert.x Web Client,确保链式调用时保持上下文传递(Mutiny默认会维护上下文,除非手动切换线程)

3. 使用@ReactiveTransactional注解(需确保上下文正确)

如果你的持久化方法属于CDI Bean,可以尝试添加@ReactiveTransactional注解,Quarkus会自动处理上下文隔离:

@Inject
Mutiny.SessionFactory sessionFactory;

@ReactiveTransactional
public Uni<List<T>> createAll(List<T> entities) {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("#createAll(T)...  {}", entities);
    }

    return sessionFactory.getCurrentSession()
            .persistAll(entities.toArray(new T[0]))
            .replaceWith(entities);
}

注意:此方法仅当调用方处于Quarkus可识别的Reactive上下文时生效,若当前上下文本身不合法,仍需结合runSubscriptionOn切换到Worker线程池。

内容的提问来源于stack exchange,提问作者A.Casanova

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 16:54:21