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); } } }