我正在构建一个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()) { %>
...........
<% } %>
我得到了我描述的例外。你有什么问题吗?提前谢谢
答案 0 :(得分:2)
在关闭数据库连接stmt1.close();
和close();
)之后,您正尝试访问ResultSet,这不起作用。 (有关详细说明,请参阅Oracle's tutorial)。
您应该检索ResultSet
的内容,然后在JSP页面中使用它,而不是让连接保持打开状态。
这样,您就可以将数据库查询的生命周期与视图生命周期分离。
答案 1 :(得分:1)
在您的示例中,当您致电ResultSet
时,stmt1.close()
已关闭。在单一方法中执行数据库访问,将结果添加到适当的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;
}
答案 2 :(得分:1)
这是因为您在执行查询后立即关闭了创建PreparedStatement
的{{1}}对象(并且可能还会关闭ResultSet
)。
来自Statement#close()
方法的文档(Connection
是PreparedStatement
的孩子):
立即释放此Statement对象的数据库和JDBC资源,而不是等待它自动关闭时发生。通常,最好在完成资源后立即释放资源,以避免占用数据库资源。
在已关闭的Statement对象上调用close方法无效。
注意:当Statement对象关闭时,其当前的ResultSet对象(如果存在)也将关闭。
强调我的。
理想情况下,您应该将Statement
的内容实现为正式集合,并将该集合发送到JSP而不是ResultSet
。
答案 3 :(得分:0)
你在声明中致电关闭,你不应该。
其次,你不应该像catch(Exception e2) {}
那样吞下exeptions。
这使得很难或无法追踪错误。
第三,在JSP中迭代ResultSet
是不好的做法。这应该在后端完成,例如(在getName
)。见How to avoid Java code in JSP files?