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
相关产品推荐
相关产品推荐

