異常
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
,Statement
和ResultSet
作爲實例變量而不是方法局部變量。當多個線程共享同一個實例時(這可能會在兩個或更多用戶同時訪問您的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;
}
將rs聲明爲局部變量比較安全,那麼您確定沒有查看以前調用的內容。即使語句失敗,上面的代碼也會返回(前一個)rs。 –