PSQLException:此 ResultSet 已关闭
Posted
技术标签:
【中文标题】PSQLException:此 ResultSet 已关闭【英文标题】:PSQLException: this ResultSet is closed 【发布时间】:2018-08-16 14:02:49 【问题描述】:我有生以来第一次遇到这个奇怪的错误,我不知道这是什么意思。我有一个类可以从 postgresql 数据库的表中检索信息,执行一些操作并返回一个带有解析元素的数组列表:
ResultSet rs = ProduttoreDCS.getProduttori();
System.out.println("Recuperato result set produttori");
ArrayList<String[]> res = new ArrayList<String[]>();
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() 方法getProduttori
到底是做什么的?如果它试图多次重用相同的 ResultSet 对象,这很容易成为问题。 (顺便说一下,没有理由将current
设置为null
。)
@jon skeet 我知道,删除它!编辑主帖
【参考方案1】:
我通过运行错误的组合遇到了同样的问题:
Postgres 版本; 休眠方言; postgres jdbc 驱动;
全部更新到最新版本解决了我的问题。
附注我知道这不是 OP 所要求的,但这是您在 Google 中搜索问题时的第一个结果。
【讨论】:
它对我有用。确保您的项目中的 postgres jdbc lib 支持 postgres 版本。如果您运行的是 PostgreSQL 9.6,请使用 PostgreSQL JDBC 9。【参考方案2】:当您在getProduttori
方法中关闭连接对象时,您的结果集将自动关闭。当您尝试重新使用它时,它将为空。
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 资源 立即而不是等待它们被自动释放。
在关闭语句时也同样适用。为了让您的代码正常工作,在获得行之前不要关闭语句和连接。
@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()
【讨论】:
所以我只需要在 getProduttori 方法中移动第一部分代码并将 ArrayList 返回给调用者方法? 是的,这确实是标准的做法 是的,我强迫我的团队升级到 java 7,这样我就可以在使用 JDBC 时跳过所有那些最终阻塞的戏剧。 :P【参考方案3】:As per Docs
当生成它的 Statement 对象关闭、重新执行或用于从多个结果序列中检索下一个结果时,ResultSet 对象会自动关闭。
您关闭了连接,然后您正在迭代,它为空。请读取数据然后关闭连接。
这里的一个好习惯是
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) ;
【讨论】:
我的心try with resource
来自 java 7 :)
@PermGenError 是啊是啊..这是现有代码 :) Haaav ..必须移动 java 7 :P【参考方案4】:
这就是问题所在:
stmt.close();
conn.close();
您正在关闭与数据库的连接。在您读取数据之前,您不能这样做 - 否则ResultSet
将如何读取它?也许一开始它会读取 一些 数据,但它并不意味着是一个断开连接的对象。
特别是来自ResultSet.close
的文档:
注意:当 Statement 对象关闭、重新执行或用于从多个结果序列中检索下一个结果时,生成它的 Statement 对象会自动关闭 ResultSet 对象。
【讨论】:
【参考方案5】:关闭连接会使结果集消失。
ResultSet 不是一个可以用来传递数据的容器,它只是一个游标的包装器。您应该遍历 resultSet 内容并将它们复制到数据结构中,然后返回数据结构。你已经这样做了,但你需要在关闭语句和连接之前这样做。
将代码改为:
public static List<String[]> getProduttori() throws ClassNotFoundException, SQLException
ArrayList<String[]> res = new ArrayList<String[]>();
/*
* 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);
【讨论】:
这个问题是如果你想将数据库调用抽象到一个单独的类中,使用这种技术会变得很困难,因为你在这里将类的数据与数据库连接方法混合在一起。 @John:同意,我更愿意在这里使用 spring 和 spring-jdbc 保持连接获取完全分开。在我看来,这似乎不是问题的一部分。以上是关于PSQLException:此 ResultSet 已关闭的主要内容,如果未能解决你的问题,请参考以下文章
PSQLException:在此 ResultSet 中找不到列名 start_value
org.postgresql.util.PSQLException:这个 ResultSet 已经被关闭。
org.postgresql.util.PSQLException:这个 ResultSet 已经被关闭。