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

java代码中的最大打开游标数超出异常,java,oracle,jdbc,Java,Oracle,Jdbc,这是我执行更新查询的代码 public boolean executeQuery(Connection con,String query) throws SQLException { boolean flag=false; try { Statement st = con.createStatement(); flag=st.execute(query); s

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

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),其中trunc(date)=to_date('“+date+”,'dd-mm-yyyy')
更新查询大约8000次

但大约2000天后,它抛出异常,因为“超过了最大打开游标数”

请建议对此进行代码更改。 @TimBiegeleisen这是获取连接的代码

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)
java.sql.SQLException:ORA-01000:超过最大打开游标数
位于oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)
位于oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:208)
位于oracle.jdbc.ttc7.Oopen.receive(Oopen.java:118)
位于oracle.jdbc.ttc7.TTC7Protocol.open(TTC7Protocol.java:472)
在oracle.jdbc.driver.OracleStatement.(OracleStatement.java:499)
位于oracle.jdbc.driver.OracleConnection.privateCreateStatement(OracleConnection.java:683)
位于oracle.jdbc.driver.OracleConnection.createStatement(OracleConnection.java:560)
位于org.apache.tomcat.dbcp.dbcp.DelegatingConnection.createStatement(DelegatingConnection.java:257)
位于org.apache.tomcat.dbcp.dbcp.PoolgDataSource$PoolGuardConnectionWrapper.createStatement(PoolgDataSource.java:216)
位于com.iisl.business.adminbo.computeindex.MoviIndexComputeBO.calculateMoviValue(MoviIndexComputeBO.java:230)

最快的解决方案之一是通过在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();

        }

您的代码有光标泄漏。这就是导致错误的原因。在遇到错误之前,您的代码似乎不太可能真正运行2000天(大约5.5年)。如果是这样的话,我敢打赌你会非常乐意每十年重启一台服务器两次

try
块中,创建一个
语句。如果在创建语句和调用
st.close()
之间引发异常,则代码将使语句保持打开状态,并泄漏光标。一旦一个会话泄漏了4000个游标,就会出现错误。增加
max\u open\u游标数
只会在错误发生时延迟,不会解决根本问题

潜在的问题是
try/catch
块需要一个
finally
,如果
try
语句保持打开状态,该语句将关闭。要使其工作,您需要在
try

finally {
  if (st != null) {
    st.close();
  }
}

正如在另一个响应中提到的,如果在语句执行期间抛出异常,您将泄漏游标,因为
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;

连接的代码在哪里?您从未读取结果,也从未关闭Connection@Jens强调
永远不会关闭连接
此外,如果发生异常,则永远不会关闭
语句
对象。应该在finally block或try/resource中完成如果您能够合并上述更改,请通过问题获得关于此问题原因的非常详细的解释。您好,谢谢您的回答,但我通过会话id获得连接对象,并在整个BO类中使用相同的连接对象。因此,如果我关闭连接,而其他方法不调用getconnection方法,它将抛出nullpointer。由于这是一个合法的系统,我不能更改每个组件中的代码。@shrikant并尝试增加一些游标。同时在finally块中关闭语句对象。:)实际上,代码一次执行insert/update查询超过2000次。thanx,我认为这个解决方案会起作用。我现在尝试了这个方法,它显示了以下错误java.sql.SQLException:ORA-00604:递归sql级别1发生错误ORA-01000:最大打开游标数exceeded@ShrikantDande-然后你有一些其他的光标泄漏。