我正在构建一个3-tier
应用程序,该应用程序使用java
类从用户界面的db
和jsp
页面检索数据。当我试图在jsp页面中调用一个返回结果集的方法时,我会得到以下错误消息:
ResultSet关闭后不允许执行操作。
例如,我有这样的方法:
public ResultSet getName(String country) throws SQLException {
String name;
try {
open();
stmt1 = con.prepareStatement(fetchPanepistimio);
stmt1.setString(1,country);
rs1 = stmt1.executeQuery();
stmt1.close();
close();
}catch(Exception e2) {
}
return rs1;
}
当我在jsp页面中写入以下内容时:
<%
ResultSet rs = panepistimio.getName(country);
while(rs.next()) { %>
...........
<% } %>
我得到了我描述的例外情况。你知道出了什么问题吗?提前感谢
您正试图在关闭数据库连接stmt1.close();
和close();
后访问ResultSet,但无法正常工作。(有关详细说明,请参阅Oracle教程)。
您应该检索ResultSet
的内容,然后在JSP页面中使用它,而不是打开连接。这样,就可以将DB查询的生命周期与视图的生命周期解耦。
这是因为您在执行查询后立即关闭创建ResultSet
的PreparedStatement
对象(并且可能还关闭Connection
)。
根据Statement#close()
方法的文档(PreparedStatement
是Statement
的子项):
立即释放此Statement对象的数据库和JDBC资源,而不是在它自动关闭时等待它发生。通常情况下,在使用完资源后立即释放资源,以避免占用数据库资源。
对已关闭的Statement对象调用方法close无效。
注意:关闭Statement对象时,其当前ResultSet对象(如果存在)也将关闭
强调我的。
理想情况下,您应该将ResultSet
的内容具体化为一个正式集合,并将该集合发送到JSP,而不是ResultSet
。
在您的示例中,当您调用stmt1.close()
时,ResultSet
是关闭的。在单一方法中执行数据库访问,将结果添加到适当的Collection
并返回。
例如:
public Collection<String> getName(String country) {
String sql = "...";
Collection<String> names = new ArrayList<>();
try(Statement statement = ...; ResultSet resultSet = statement.executeQuery(sql)){
while(resultSet.next()) {
names.add(resultSet.getString(...));
}
} catch (SQLException e) {
// LOG
}
return names;
}
您对语句调用了close,但不应该这样做。
第二,你不应该像catch(Exception e2) {}
那样轻信口头禅。这使得跟踪错误变得困难或不可能。
第三,在JSP中迭代ResultSet
不是一种好的做法。这应该在后端完成,例如(在getName
中)。请参阅如何避免JSP文件中的Java代码?