最大打开游标超出了java代码中的异常

时间:2016-09-27 05:09:18

标签: java oracle jdbc

这是我执行更新查询的代码

public  boolean executeQuery(Connection con,String query) throws SQLException
    {
            boolean flag=false;
        try
        {
            Statement st = con.createStatement();
            flag=st.execute(query);
            st.close();
            st=null;
            flag=true;


        }
        catch (Exception e) 
        {
            flag=false;
            e.printStackTrace();
            throw new SQLException(" UNABLE TO FETCH INSERT");          
        }
        return flag;
    }

最大打开光标设置为4000 代码正在执行  update tableA set colA ='x',lst_upd_date = trunc(sysdate) where trunc(date) = to_date('"+date+"','dd-mm-yyyy') 更新查询大约8000次

但是在大​​约2000天之后它的抛出异常为“最大开放游标超过”

请为此建议代码更改。 @TimBiegeleisen这里是代码get connecttion

public  Connection getConnection(String sessId)
    {

        Connection connection=null;

         setLastAccessed(System.currentTimeMillis());

        connection=(Connection)sessionCon.get(sessId);

            try 
            {
                if(connection==null || connection.isClosed()  )
                {

                if ( ds == null )
                {
                    InitialContext ic = new InitialContext();
                    ds = (DataSource) ic.lookup("java:comp/env/iislDB");
                }

                connection=ds.getConnection();

                sessionCon.put(sessId, connection);

                }
            }
            catch (SQLException e) 
            {
                e.printStackTrace();    
            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }


        return connection;
    }

`

错误堆栈如下所示

java.sql.SQLException: ORA-01000: maximum open cursors exceeded

    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)
    at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:208)
    at oracle.jdbc.ttc7.Oopen.receive(Oopen.java:118)
    at oracle.jdbc.ttc7.TTC7Protocol.open(TTC7Protocol.java:472)
    at oracle.jdbc.driver.OracleStatement.<init>(OracleStatement.java:499)
    at oracle.jdbc.driver.OracleConnection.privateCreateStatement(OracleConnection.java:683)
    at oracle.jdbc.driver.OracleConnection.createStatement(OracleConnection.java:560)
    at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.createStatement(DelegatingConnection.java:257)
    at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.createStatement(PoolingDataSource.java:216)
    at com.iisl.business.adminbo.computeindex.MoviIndexComputeBO.calculateMoviValue(MoviIndexComputeBO.java:230)

3 个答案:

答案 0 :(得分:1)

最快的解决方案之一是通过在SQL提示符上发出以下命令来增加每个连接可以处理的游标:

alter system set open_cursors = 1000 

此外,在代码中添加finally块并关闭连接以帮助在异常发生时关闭游标。

此外,运行此查询以查看实际光标的打开位置。

select  sid ,sql_text, count(*) as "OPEN CURSORS", USER_NAME from v$open_cursor



finally {

     if (connection!=null) {

     connection.close();

        }

答案 1 :(得分:1)

您的代码有光标泄漏。这是造成错误的原因。在遇到错误之前,您的代码似乎不太可能在2000天(大约5。5年)内完成。如果是这种情况,我敢打赌,你十分乐意在十年内重启服务器两次。

try区块中,您可以创建Statement。如果在创建语句的时间和调用st.close()的时间之间抛出异常,则代码将使语句保持打开状态,并且您将泄漏游标。一旦会话泄露了4000个游标,您就会收到错误。增加max_open_cursors只会在错误发生时延迟,它不会解决根本问题。

根本问题是,try/ catch阻止需要finallyStatement如果try处于打开状态,则关闭st。为此,您需要在try

之外声明finally { if (st != null) { st.close(); } }
par, cov = curve_fit(f, x, y, p0=[1.,1.,1.,74.])

答案 2 :(得分:1)

如在另一个响应中所提到的,如果在语句执行期间抛出异常,则会泄漏游标,因为st.close()将不会被执行。您可以使用Java的try-with-resources语法来确保语句对象已关闭:

    try (Statement st = con.createStatement())
    {
        flag=st.execute(query);
        flag=true;
    }
    catch (Exception e) 
    {
        flag=false;
        e.printStackTrace();
        throw new SQLException(" UNABLE TO FETCH INSERT");          
    }
    return flag;