如何验证游标是否在数据库中关闭?

时间:2018-07-31 12:00:05

标签: java oracle jdbc

在我们的Web应用程序中,我们经常遇到此问题

ORA-01000 maximum open cursors exceeded

我知道这与代码没有正确关闭游标(ResultSetPreparedStatement等)有关。

示例:

public List<Employee> getAllEmployees() throws DatabaseException{
        Connection conn = DatabaseHelper.getConnection(); //Get a connection from the connection pool

        PreparedStatement pst = null;
        ResultSet rs = null;

        List<Employee> emps = new ArrayList<Employee>();
        try {
            pst = conn.prepareStatement("SELECT * FROM EMPLOYEE ORDER BY EMP_ID");
            rs = pst.executeQuery();
            while(rs.next()) {
                //Do something
            }
        } catch (SQLException e) {
            logger.error("ERROR getting all employees", e);
            throw new DatabaseException("Could not get all employees due to an internal error", e);
        } finally {
            try { pst.close(); } catch(Exception ignore) {} //Close the prepared statement
            try { rs.close(); } catch(Exception ignore) {} //Close the Resultset
            try { conn.close(); } catch(Exception ignore) {} ////Close the connection, thus returning it to the pool
        }

        return emps;
    }

尽管我知道我正在关闭游标和finally块中的连接,但我不了解的是我如何才能实际验证游标在Oracle数据库中是否已关闭?

我当前正在运行以下查询(假设我的数据库用户名是EMP

select * from v$open_cursor where sid in (select sid from v$session where username='EMP' and program ='JDBC Thin Client');

这为我提供了通过JDBC瘦客户端连接的会话的打开游标的行列表。但是,即使在调用pst.close()rs.close()conn.close()之后,查询仍会返回相同的行,这似乎表明游标仍处于打开状态。

我使用JProfiler检查泄漏。但是,它告诉我是否要关闭Connection对象,但不会告诉我PreparedStatementStatementResultSet

我已经参考了以下帖子,并且已经按照说明进行了操作,但是它们似乎都没有回答我的问题,即如何验证Oracle中是否关闭了游标(使用SQL Developer或其他方法)工具)?

Link to a very exhaustive explanation on this topic

1 个答案:

答案 0 :(得分:0)

首先也是最重要的一点,v$open_cursor 不是当前打开的游标列表。为此,我认为您需要v$sesstatv$statname的某种组合,但我不确定。

您的open_cursors参数设置为什么?我认为默认值为50,但是Oracle建议将其至少设置为500。