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

Quarkus 3.2.0调用存储过程出现Hibernate Session线程不安全异常

问题原因分析及解决方案

核心原因

这个异常的本质是Quarkus 3.x升级后,Hibernate ORM(从5.x升至6.x)对Session的线程安全约束大幅强化,同时Quarkus自身的会话/事务管理逻辑也做了调整,而你的代码仍沿用Quarkus 2.6时代的实现,导致了线程安全冲突。具体分以下几点:

  1. Hibernate 6的Session线程安全检查升级
    Hibernate 5对跨线程访问Session的行为可能仅做静默警告,但Hibernate 6直接通过断言强制阻止这类不安全操作。如果你的Repository代码中存在跨线程复用Session实例、在非事务上下文长期持有Session引用的情况,就会触发AssertionFailure。

  2. 存储过程调用的会话管理逻辑变更
    Quarkus 3.x对JPA事务的传播和Session绑定规则做了调整:

  • 若你通过EntityManager.unwrap(Session.class)手动获取Session调用存储过程,且未在@Transactional注解覆盖的上下文内执行,Session可能被错误地共享到多个线程;
  • Quarkus 2.6的默认会话机制允许临时Session在非事务场景下复用,但3.x版本强制Session与当前线程绑定。
  1. SYS_REFCURSOR处理的API兼容性问题
    Hibernate 6对Oracle游标类型的处理API有兼容性变化,若你仍使用Hibernate 5的旧方式(比如Session.createSQLQuery配合registerOutParameter)处理SYS_REFCURSOR,可能导致游标未及时释放,进而引发Session状态混乱,触发线程安全断言。

  2. Quarkus事务配置默认值变更
    Quarkus 3.x修改了quarkus.hibernate-orm.session-handling等核心配置的默认值,若你的application.properties未显式指定会话处理策略,可能导致Session被意外共享到多线程环境。


排查与修复步骤

  1. 确保方法被事务注解覆盖
    调用存储过程的Repository方法必须添加@Transactional注解,让Quarkus自动管理Session的创建、绑定与销毁,避免手动操作带来的线程安全问题:
@Transactional
public List<YourEntity> fetchDataFromProcedure(String param) {
    // 存储过程调用逻辑
}
  1. 替换为Hibernate 6兼容的存储过程调用方式
    使用EntityManager.createStoredProcedureQuery替代旧的Session调用方式,正确处理SYS_REFCURSOR:
@Transactional
public List<YourEntity> callProcedure(String param) {
    StoredProcedureQuery query = entityManager.createStoredProcedureQuery("YOUR_PROC_NAME", YourEntity.class);
    query.registerStoredProcedureParameter(1, String.class, ParameterMode.IN);
    query.registerStoredProcedureParameter(2, Class.class, ParameterMode.REF_CURSOR);
    query.setParameter(1, param);
    query.execute();
    return query.getResultList();
}
  1. 修正手动Session操作逻辑
    若代码中存在手动获取Session的逻辑,必须用try-with-resources块确保Session及时关闭,避免泄漏:
@Transactional
public void manualSessionCall(String param) {
    try (Session session = entityManager.unwrap(Session.class)) {
        // 存储过程调用逻辑
    }
}
  1. 显式配置会话线程绑定策略
    在application.properties中添加以下配置,强制Session与当前线程绑定:
quarkus.hibernate-orm.session-handling=thread

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:55:10