在JPA中调用存储过程并及时将资源释放
问题
最近发现在调用某个API执行batch job(批处理)时,每当数据量达到一定数量时,后续的记录都会出现以下错误:
oracle ORA-01000: maximum open cursors exceeded
原因
- 排查发现该batch job中包含调用存储过程的逻辑,并且未释放资源
这就导致了在一个事务中处理多条记录时开启了多个游标而未关闭,导致游标数激增 - 而在单个用户日常使用的场景,往往都是一个事务中处理单条记录或少量记录,在 事务完成 后,数据库会 自动关闭 这期间开启的游标,所以在用户日常使用时,这个问题没有被发现
SQL
查看当前打开的游标数目:
select count(*) from v$open_cursor;
完整示例代码
public void test(String id) {
StoredProcedureQuery procedureQuery = em.createStoredProcedureQuery("TEST_PKG.test");
try{
procedureQuery.registerStoredProcedureParameter("p_id", String.class, ParameterMode.IN);
procedureQuery.setParameter("p_id", id);
procedureQuery.execute();
}finally {
procedureQuery.unwrap(ProcedureOutputs.class).release();
}
}
关闭资源的语句:
procedureQuery.unwrap(ProcedureOutputs.class).release();
注意点
- 无论调用存储过程是否成功,必须将资源释放,避免资源占用导致出现问题或影响其他数据库操作
- 注意区分日常用户使用的场景和批处理的场景的区别,能够更好的分析排查BUG原因
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统