ResultSet在java中关闭后不允许操作

时间:2012-12-15 20:53:13

标签: java mysql jsp jdbc resultset

我有一个名为Database的类。

    public class Database {
    public Connection connect = null;
    public Statement st = null;
    public PreparedStatement ps = null;
    public ResultSet rs = null;

    public boolean connectDB() throws Exception {
      try {

      Class.forName("com.mysql.jdbc.Driver");

      connect = DriverManager
        .getConnection("jdbc:mysql://localhost/ots?"
              + "user=root&password=mongolia");
    } catch (Exception e) {
      System.out.println(e);
    }
    return true;
   }

    public void disconnectDB() {
    try {
      if (rs != null) {
        rs.close();
      }

      if (st != null) {
        st.close();
      }

      if (connect != null) {
        connect.close();
      }
    } catch (Exception e) {

    }
    }

     } 

和名为user的类,它正在扩展Database类

public class User extends Database {
    public ResultSet fetchTable(){
        try{
            connectDB();            
            st = connect.createStatement();
            rs = st.executeQuery("SELECT * FROM user");         
        }catch(Exception e){
            System.out.println(e);
        }finally{
            disconnectDB();
        }
        return rs;
    }
  }
//Inside JSP page
  User user = new User();
  ResultSet data = user.fetchTable();

  //getting exception in the data.next() function
  //java.sql.SQLException: Operation not allowed after ResultSet closed

  while(data.next()){
        out.println("<p>"+data.getInt(0)+"</p>");
   }

//getting exception in the data.next() function
//java.sql.SQLException: Operation not allowed after ResultSet closed

1 个答案:

答案 0 :(得分:6)

完全可以预料到例外情况。您正在连接数据库,获取结果集,关闭数据库和结果集,然后尝试访问已关闭的结果集。

这不是JDBC的工作方式。

您需要在检索结果集后直接将结果集映射到List<User>,然后关闭结果集并返回List<User>

对于一些具体的例子,请回答这个问题的答案:JDBC driver throws "ResultSet Closed" exception on empty ResultSet


对于具体问题

无关,您在代码中遇到了其他严重问题。除其他外,您已将ConnectionStatementResultSet声明为实例变量,而不是方法局部变量。当多个线程之间共享相同的实例时(当两个或多个用户同时访问您的Web应用程序时可能会发生这种情况),这将很难实现。我也会解决这个问题。


更新:到目前为止发布的其他答案建议删除disconnectDB()调用或仅在迭代其他方法的结果集后调用它。这是错误。你应该从方法中传递ResultSet。您的代码仍然是线程安全的,如果出现异常,您仍然会面临泄漏资源的风险。您应该在同一个方法块中创建,使用和关闭它。这是正确的方法,从上述问题中复制:

public List<User> list() throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    List<User> users = new ArrayList<User>();

    try {
        connection = database.getConnection();
        statement = connection.prepareStatement("SELECT id, username, email, age FROM user");
        resultSet = statement.executeQuery();
        while (resultSet.next()) {
            users.add(new User(
                resultSet.getLong("id"),
                resultSet.getString("username"),
                resultSet.getString("email"),
                resultSet.getInteger("age")));
        }
    } finally {
        close(resultSet, statement, connection);
    }

    return users;
}