2012-12-15 64 views
0

我有一個名爲Database的類。完全預期被叫用戶被延伸Database類在java中關閉ResultSet後不允許操作

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 
+0

將rs聲明爲局部變量比較安全,那麼您確定沒有查看以前調用的內容。即使語句失敗,上面的代碼也會返回(前一個)rs。 –

回答

6

異常

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) { 

    } 
    } 

    } 

和類。您正在連接數據庫,獲取結果集,關閉數據庫和結果集,然後嘗試訪問已關閉的結果集。

這不是JDBC應該如何工作的。

您需要將檢索結果集直接映射到List<User>,然後關閉結果集並返回List<User>

對於一些具體的例子,頭對這個問題的答案:JDBC driver throws "ResultSet Closed" exception on empty ResultSet


無關的具體問題,您在代碼中的其他嚴重問題。其中,您已宣佈Connection,StatementResultSet作爲實例變量而不是方法局部變量。當多個線程共享同一個實例時(這可能會在兩個或更多用戶同時訪問您的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; 
} 
+0

很多優秀的點。程序員發現自己在JSP頁面中編寫Java「scriplets」時,他們應該考慮到「代碼味道」,備份並找到更好的解決方案。 – Marvo

+0

另一個選擇是使用'CachedRowSet'實現,它具有'ResultSet'作爲接口,但是沒有連接。 –

相關問題