PSQLException:此ResultSet已关闭

我生命中第一次出现这个奇怪的错误,我不知道它意味着什么。 我有一个类从postgresql数据库的表中检索信息,做一些操作并返回带有解析元素的arraylist:

ResultSet rs = ProduttoreDCS.getProduttori(); System.out.println("Recuperato result set produttori"); ArrayList res = new ArrayList(); while (rs.next()) { String[] current = new String[6]; current[0] = Integer.toString(rs.getInt("partita_iva")); current[1] = rs.getString("nome"); current[2] = rs.getString("cognome"); current[3] = rs.getString("via_sede"); current[4] = rs.getString("citta_sede"); current[5] = rs.getString("provincia_sede"); res.add(current); current = null; } return res; 

错误在“while”行上。

 public static ResultSet getProduttori() throws ClassNotFoundException, SQLException { /* * retrieve all record from produttori table */ Connection conn = null; ResultSet res = null; Statement stmt = null; String query = "SELECT * FROM produttore"; conn = ConnectionManager.getConnection(); System.out.println("Connection obtained by ProduttoreDCS class"); stmt = conn.createStatement(); res = stmt.executeQuery(query); stmt.close(); conn.close(); return res; } 

当您在getProduttori方法中关闭连接对象时, 结果集将自动关闭 。 当你尝试重新使用它时,它将为null。

 ResultSet rs = ProduttoreDCS.getProduttori(); = null, as you have closed the connection in getProduttori method, which will automatically close the resultset thus, it returns null. 

来自Connection#close

立即释放此Connection对象的数据库和JDBC资源,而不是等待它们自动释放。

在关闭Statement时也适用相同的方法。为了使你的代码工作,不要关闭Statement和Connection,直到获得行。

@Baadshah已经向您展示了标准方式。 如果您使用的是java 7+,则可以使用try-with-resource块,这将使您的生活更简单。

  try(Connection conn = gettheconn){ get the statement here get the result set perform your ops } catch(SQLException ex){ ex.printstacktrace(); } 

如果您观察到,没有finally块,一旦您自动退出try块,您的连接对象将被关闭。您不必明确调用Connection#close()

这就是问题:

 stmt.close(); conn.close(); 

您正在关闭与数据库的连接。 在读取数据之前,您不能这样做 – 否则ResultSet将如何读取它? 也许它会在开始时读取一些数据,但它并不意味着是一个断开连接的对象。

特别是,从ResultSet.close的docuemntation:

注意:当Statement对象关闭,重新执行或用于从多个结果序列中检索下一个结果时,Statement对象会自动由Statement对象关闭。

根据文件

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

你关闭连接,然后你正在迭代,它是null。请读取数据,然后关闭连接。

这里的一个好习惯是

 Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = stmt = conn.prepareStatement("sql"); rs = stmt.executeQuery(); //DO SOME THING HERE } catch { // Error Handling } finally { try { if (rs != null) rs.close(); } catch (Exception e) {}; try { if (stmt != null) stmt.close(); } catch (Exception e) {}; try { if (conn != null) conn.close(); } catch (Exception e) {}; } 

关闭连接会使resultSet消失。

ResultSet不是可用于传递数据的容器,它只是游标周围的包装器。 您应该运行resultSet内容并将它们复制到数据结构中,然后返回数据结构。 您已经这样做了,但是在关闭语句和连接之前需要这样做。

将代码更改为:

 public static List getProduttori() throws ClassNotFoundException, SQLException { ArrayList res = new ArrayList(); /* * retrieve all record from produttori table */ Connection conn = null; ResultSet rs = null; Statement stmt = null; String query = "SELECT * FROM produttore"; conn = ConnectionManager.getConnection(); try { System.out.println("Connection obtained by ProduttoreDCS class"); stmt = conn.createStatement(); try { rs = stmt.executeQuery(query); while (rs.next()) { String[] current = new String[6]; current[0] = Integer.toString(rs.getInt("partita_iva")); current[1] = rs.getString("nome"); current[2] = rs.getString("cognome"); current[3] = rs.getString("via_sede"); current[4] = rs.getString("citta_sede"); current[5] = rs.getString("provincia_sede"); res.add(current); } return res; } finally { try { stmt.close(); } catch (SQLException e) { log.error(e); } } } finally { try { conn.close(); } catch (SQLException e) { log.error(e); } } }