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

SpringBoot调用Oracle存储过程:存储过程执行完毕但executeUpdate未结束

问题:PL/SQL存储过程执行完毕,但Java端executeUpdate()始终未返回

我们使用SpringBoot 3.x搭配Java 21,通过Hibernate调用Oracle数据库中的PL/SQL存储过程,该过程完整执行需10-12分钟。目前数据库表中已通过TRACE_PR日志确认存储过程已执行完毕,但Java代码中的storedProcedure.executeUpdate()方法仍在执行,始终不结束。

相关代码片段

Java代码

/** The entity manager. */
@PersistenceContext
EntityManager entityManager;

@jakarta.transaction.Transactional
public void callStoredProcedure(String procdurename, Integer jobId) {
    StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery(procdurename)
            .registerStoredProcedureParameter(0, Integer.class, ParameterMode.IN);

    storedProcedure.setParameter(0, jobId);
    try {
        LOGGER.info("Execute Update....... ");
        storedProcedure.executeUpdate();
        LOGGER.info("Execute Update.......End ");
    } finally {
        storedProcedure.unwrap(ProcedureOutputs.class).release();
    }
}

PL/SQL存储过程

PROCEDURE stored_Procedure_db(i_job_id in NUMBER) IS
   L_PROC_NAME VARCHAR2(100) := C_MODULE_NAME || '.stored_Procedure_db';
   L_TRCSTRING VARCHAR2(1024);
   l_Step_Name VARCHAR2(20) := 'Test';
 BEGIN
   TRACE_PA.TRACE_PR(L_PROC_NAME, 20, 'Start:' || i_Job_Id, 1);
   tr_objects_pr_primary(i_job_id);
   tr_objects_pr_secondary(i_job_id);
   TRACE_PA.TRACE_PR(L_PROC_NAME, 20, 'Ende:' || i_Job_Id);
 EXCEPTION
   WHEN OTHERS THEN
     begin
       L_TRCSTRING := 'unhandled exception ' || SQLERRM;
       RAISE_APPLICATION_ERROR(-20068, L_TRCSTRING);
     end;
   
 END stored_Procedure_db;

可能的原因及排查建议

1. Spring事务机制阻塞

方法上的@jakarta.transaction.Transactional注解会让Spring在方法结束时自动提交事务。如果存储过程执行完毕后,数据库端存在未释放的锁、事务未完成的隐式操作,Spring会一直等待事务提交完成。

排查建议:

  • 临时去掉@Transactional注解,直接调用存储过程,观察是否能正常返回。如果恢复正常,说明是事务管理导致的阻塞,可考虑在存储过程内部自行控制事务(比如添加COMMIT;),或者调整Spring事务的传播属性。

2. 隐式结果集未读取/关闭

即使存储过程只定义了IN参数,若子过程tr_objects_pr_primary或tr_objects_pr_secondary中执行了未处理的SELECT语句、未关闭的游标,Oracle会将结果集返回给客户端。Hibernate的StoredProcedureQuery会一直等待读取所有结果集才会返回。

排查建议:

  • 检查存储过程及子过程的代码,确保所有游标都显式关闭,所有SELECT语句都有对应的处理(比如用INTO子句接收结果);
  • 在存储过程末尾添加COMMIT;(如果业务允许),强制结束事务并释放资源。

3. 数据库会话状态异常

存储过程日志显示结束,但数据库会话可能仍在执行后台操作(比如大事务的日志写入、索引维护),或者处于等待状态。

排查建议:

  • 执行Oracle查询查看会话状态:
    SELECT sid, serial#, status, wait_class, event 
    FROM v$session 
    WHERE program LIKE '%你的应用标识%' AND username = '数据库用户名';
    
    • 如果会话状态为INACTIVE但Java端仍等待,说明驱动未正确接收结束信号;
    • 如果状态为WAITING,查看event字段确认等待事件(比如锁等待、IO等待),针对性解决。

4. Oracle驱动版本兼容问题

使用的ojdbc版本与SpringBoot 3.x、Java 21不兼容,可能导致驱动在处理长耗时存储过程时出现阻塞,无法正确接收存储过程完成的信号。

排查建议:

  • 升级至适配Java 21和SpringBoot 3.x的最新ojdbc版本(推荐ojdbc11的最新稳定版),确保驱动与JDK、框架版本匹配。

5. 连接池或网络超时设置不匹配

数据库连接池(如HikariCP)的超时设置过长,或者网络层面(防火墙、TCP)存在超时,可能导致连接假死,Java端误以为存储过程仍在执行。

排查建议:

  • 调整连接池参数:比如HikariCP的connectionTimeout设置为合理值(大于存储过程执行时间),maxLifetime避免长连接老化;
  • 检查网络防火墙是否有长连接超时限制,确保允许存储过程执行时长的连接存活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:02:09