在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原因
posted @ 2022-10-19 14:17  229  阅读(201)  评论(0编辑  收藏  举报