获取 java.sql.SQLException:ResultSet 关闭后不允许操作

Posted

技术标签:

【中文标题】获取 java.sql.SQLException:ResultSet 关闭后不允许操作【英文标题】:Getting java.sql.SQLException: Operation not allowed after ResultSet closed 【发布时间】:2011-08-16 00:00:24 【问题描述】:

当我执行以下代码时,我得到一个异常。我认为这是因为我正在使用相同的连接对象准备新的声明。我应该如何重写它以便我可以创建一个准备好的语句并开始使用 rs2?即使连接到同一个数据库,我是否必须创建一个新的连接对象?

    try 
    
        //Get some stuff
        String name = "";
        String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
        ResultSet rs = statement.executeQuery(sql);
        if(rs.next())
        
            name = rs.getString("name");
        

        String sql2 = "SELECT `id` FROM  `profiles` WHERE `id` =" + profId + ";";
        ResultSet rs2 = statement.executeQuery(sql2);
        String updateSql = "INSERT INTO `blah`............"; 
        PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);    

        while(rs2.next()) 
         
            int id = rs2.getInt("id");
            int stuff = getStuff(id);

            pst.setInt(1, stuff);
            pst.addBatch();

        

        pst.executeBatch();

     
    catch (Exception e) 
    
        e.printStackTrace();
    

private int getStuff(int id)


    try
       

            String sql = "SELECT ......;";
            ResultSet rs = statement.executeQuery(sql);

            if(rs.next())
            
                return rs.getInt("something");

            
            return -1;
    //code continues

【问题讨论】:

第一次在while被调用时发生? 不,它发生在第二个循环。因为在此期间,我再次调用了一个私有方法,该方法初始化了另一个 ResultSet 并执行了更多查询。 你能显示在第一次迭代中执行的其余代码吗 会不会因为其他 ResultSet 而发生异常? 【参考方案1】:

问题在于您在getStuff() 中获取数据的方式。每次访问getStuff() 时,您都会获得一个新的ResultSet,但您不会关闭它。

这违反了Statement 类的期望(见这里-http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):

默认情况下,每个 Statement 对象只能同时打开一个 ResultSet 对象。因此,如果一个 ResultSet 对象的读取与另一个 ResultSet 对象的读取交错,则每个对象都必须由不同的 Statement 对象生成。 Statement 接口中的所有执行方法都会隐式关闭一个语句的当前 ResultSet 对象,如果存在打开的对象。

更糟糕的是调用代码中的rs。它也从statement 字段派生而来,但并未关闭。

底线:您同时打开了多个与同一 Statement 对象相关的 ResultSet

【讨论】:

酷。我在 getStuff() 中创建了一个新的 Statement 并解决了问题。 您是否尝试过关闭结果集?似乎比创建新语句更清洁。【参考方案2】:

ResultSet 对象会自动 当 Statement 对象关闭时 生成它被关闭,重新执行, 或用于检索下一个结果 来自多个结果的序列。

我猜在while(rs2.next()) 之后,您正试图从 rs1 访问某些内容。但它已经关闭,因为您重新执行语句以从中获取 rs2。由于您没有关闭它,我相信它在下面再次使用。

【讨论】:

刚刚添加了更多代码。之后我实际上没有从 rs1 得到任何东西。 那些古老的 Java 类设计得如此怪异:(

以上是关于获取 java.sql.SQLException:ResultSet 关闭后不允许操作的主要内容,如果未能解决你的问题,请参考以下文章

java.sql.SQLException:无法从底层数据库获取连接! — HSQLDB

获取异常 java.sql.SQLException: ORA-03115: 不支持的网络数据类型或表示

获取 java.sql.SQLException:ResultSet 关闭后不允许操作

获取noclassfoundexception:jdk 11的intellij idea中的java.sql.SQLException

Bug解决:获取JDBC连接失败;嵌套异常是java.sql.SQLException:无法从底层数据库获取连接

Spring Batch 无法获取 last_insert_id();嵌套异常是 java.sql.SQLException: Lock wait timeout exceeded;