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

Quarkus + Hibernate Reactive Panache实体持久化异常排查

问题分析与解决方案

核心问题

你遇到的异常根源是手动订阅Uni脱离了Quarkus的请求上下文:
在接口代码中,你使用subscribe().with(...)手动触发Category.add(category)的异步订阅,这部分代码会脱离当前请求的上下文环境。而Quarkus的Hibernate Reactive Session是与请求上下文绑定的,当连续调用接口时,前一次请求的上下文被销毁,手动订阅的异步操作仍在运行,此时无法找到可用的Session,从而抛出异常。

@WithSessionOnDemand注解仅在Quarkus管理的上下文(如请求上下文、事务上下文)内生效,手动订阅的代码不在该范围内,所以注解无法起作用。

修复方案

不要手动订阅Uni,而是将创建分类的操作与查询列表的操作合并到同一个Uni链中,让Quarkus统一管理上下文和订阅。以下是两种可行的修改方式:

方式1:顺序执行(推荐,确保列表包含新创建的分类)

@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<Category>> list2() {
    Category category = new Category();
    category.name = "test quarkus 3";
    
    // 先完成分类创建,再查询所有分类,全程共享请求上下文
    return Category.add(category)
            .onItem().invoke(addedCat -> System.out.println(addedCat.id)) // 用invoke替代subscribe,保持Uni链
            .chain(ignored -> Category.listAll()); // 链式调用查询列表
}

方式2:并行执行(无需等待创建完成即可返回列表)

如果不需要确保返回的列表包含新创建的分类,可以并行执行两个操作,但同样避免手动订阅:

@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<Category>> list2() {
    Category category = new Category();
    category.name = "test quarkus 3";
    
    Uni<Category> addUni = Category.add(category)
            .onItem().invoke(addedCat -> System.out.println(addedCat.id));
    
    // 并行执行创建和查询操作,最终返回分类列表
    return Uni.combine().all().unis(addUni, Category.listAll())
            .combinedWith((addedCat, categoryList) -> categoryList);
}

补充说明

Panache.withTransaction本身已经会自动管理Session和事务,但前提是它运行在Quarkus的上下文环境中。手动订阅破坏了这个上下文绑定,因此即使添加@WithSessionOnDemand注解也无法解决问题。

内容的提问来源于stack exchange,提问作者smillis12

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:27:47