获取 java.sql.SQLException:结果集关闭后不允许操作

当我执行以下代码时,我得到一个异常。我想这是因为我正在准备与他相同的连接对象的新语句。我应该如何重写它,以便我可以创建一个准备好的语句并使用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

答案 1

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

这违反了类的期望(请参阅此处 - http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):Statement

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

更糟糕的是来自调用代码。它也是从场外派生的,但它没有关闭。rsstatement

底线:您有几个与同时打开的同一对象相关的对象。ResultSetStatement


答案 2

当生成 ResultSet 对象的 Statement 对象关闭、重新执行或用于从多个结果序列中检索下一个结果时,将自动关闭该对象。

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


推荐