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

时间:2014-12-06 19:19:24

标签: java mysql jdbc resultset sqlexception

我正在尝试从MySQL数据库中获取信息。我可以连接并执行诸如将数据精确插入表格之类的内容,虽然我收到了ResultSet,但我无法阅读它。这是我的代码:

public ResultSet executeQuery(String query) {
    Statement stmt = null;
    ResultSet rs = null;

    try {
        stmt = conn.createStatement();
        rs = stmt.executeQuery(query);

        if (stmt.execute(query)) {
            rs = stmt.getResultSet();
        }
        return rs;
    }
    catch (SQLException ex){
        System.err.println("SQLException: " + ex.getMessage());
        System.err.println("SQLState: " + ex.getSQLState());
        System.err.println("VendorError: " + ex.getErrorCode());
    }
    finally {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException sqlEx) { } // ignore

            stmt = null;
        }
    }
    return null;
}

尝试阅读ResultSet

ResultSet set = executeQuery("SELECT rank FROM players");
try {
    while(set.next()) {
          System.out.println(set.getInt("rank") + "");
    }
} catch(Exception ex) {
    ex.printStackTrace();
} finally {
    try {
        set.close();
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

我收到此错误:

  

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

我一整天都在互联网上和不同的论坛上。我的代码出了什么问题?

3 个答案:

答案 0 :(得分:0)

您在executeQuery中的finally块会在您对结果进行迭代之前关闭您的语句。

答案 1 :(得分:0)

TL; DR executeQuery关闭Statement

来自JavaDoc for Statement.close

  

释放此Statement对象的数据库和JDBC资源   立即而不是等待它发生的时候   自动关闭。

close() 之前Statement 您已阅读ResultSet。关闭Statement会导致与该ResultSet关联的所有Statement个实例也被关闭。

您需要将Consumer<ResultSet>传递给其他方法,并在ResultSet开启时处理Statement

public void executeQuery(final String query, final Consumer<ResultSet> consumer) {
    try(final Statement stmt = conn.createStatement();
        final ResultSet rs = stmt.executeQuery(query)) {
            consumer.accept(rs);
    }
    catch (SQLException ex){
        System.err.println("SQLException: " + ex.getMessage());
        System.err.println("SQLState: " + ex.getSQLState());
        System.err.println("VendorError: " + ex.getErrorCode());
    }
}

我还修改了你的代码:

  1. 我已将try..finally替换为try-with-resources
  2. 您可以通过调用stmt.executeQuery(query)然后stmt.execute(query)来执行两次查询。这不仅浪费,而且您丢失了对第一个ResultSet的引用,如果Statement.close未关闭所有关联的结果集,则会导致内存泄漏。

答案 2 :(得分:0)

嗯,有两件事 -

1)我不明白你的方法中有execute()和executeQuery()的原因吗?我认为executeQuery()应该适合你。

2)在迭代结果集之前不要关闭语句。将它作为实例变量并在迭代后关闭它。