2009-11-28 72 views
9

我在SQLite的JDBC驅動程序中遇到問題。JDBC驅動程序在空ResultSet上拋出「ResultSet Closed」異常

我正在用SELECT語句執行查詢。

如果我得到一個空的ResultSet(0行),那麼當調用getString(1)時,我看到一個「Closed ResultSet」異常拋出。

沒有太多的前JDBC的經驗,我的理論(我不能爲ResultSet通過的JavaDoc確認)是

  • getString(1)不上一個空(零行)的結果集的工作(通過設計或由於一個bug)
  • ResultSet「開放「標誌設置爲false零行(再次,通過設計或錯誤)

我看到這個bug report但我不知道這是否是相關。

我qeustions是:

  1. 以上是正確的理論?
  2. 這是一個錯誤?特徵? (如果有的話,有人可以指向文檔嗎?)
  3. 它是特定於所有JDBC驅動程序中SQLIte的JDBC還是通用的ResultSet
  4. 做這種事情的正確方法是什麼?

對於#4,我的解決方法是在executeQuery()之後使用isFirst()調用,以檢查結果集中是否有任何行。這是最佳實踐方法嗎? (我也可以簡單地選擇計數插入因爲我並不真的需要一個結果集,只是零非零的標誌,但如果我關心select的結果,我想知道正確的事情)

謝謝!

+1

謝謝大家!非常照亮! – DVK 2009-11-29 05:16:25

回答

17

不是空的,但執行以下操作總是故障

resultSet = statement.executeQuery(sql); 
string = resultSet.getString(1); // Epic fail. The cursor isn't set yet. 

這是不是一個錯誤。這是documented behaviour。每個decent JDBC tutorial提到它。在能夠訪問任何數據之前,需要使用next()來設置ResultSet的遊標。

如果您確實有興趣是否假定唯一行存在或不,那麼只需檢查next()的結果。例如,在一個虛構的UserDAO類:

public boolean exist(String username, String password) throws SQLException { 
    boolean exist = false; 

    try (
     Connection connection = database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement("SELECT id FROM user WHERE username = ? AND password = MD5(?)"); 
    ) { 
     statement.setString(1, username); 
     statement.setString(2, password); 

     try (ResultSet resultSet = statement.executeQuery()) { 
      exist = resultSet.next(); 
     } 
    } 

    return exist; 
} 

如果你真的希望只一個行,那麼就這樣做:

public User find(String username, String password) throws SQLException { 
    User user = null; 

    try (
     Connection connection = database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement("SELECT id, username, email, birthdate FROM user WHERE username = ? AND password = MD5(?)"); 
    ) { 
     statement.setString(1, username); 
     statement.setString(2, password); 

     try (resultSet = statement.executeQuery()) { 
      if (resultSet.next()) { 
       user = new User(
        resultSet.getLong("id"), 
        resultSet.getString("username"), 
        resultSet.getString("email"), 
        resultSet.getDate("birthdate")); 
      } 
     } 
    } 

    return user; 
} 

,然後就處理它相應的業務/域對象,例如

User user = userDAO.find(username, password); 

if (user != null) { 
    // Login? 
} 
else { 
    // Show error? 
} 

如果你真的希望只許多行,那麼就這樣做:

public List<User> list() throws SQLException { 
    List<User> users = new ArrayList<User>(); 

    try (
     Connection connection = database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement("SELECT id, username, email, birthdate FROM user"); 
     ResultSet resultSet = statement.executeQuery(); 
    ) { 
     while (resultSet.next()) { 
      users.add(new User(
       resultSet.getLong("id"), 
       resultSet.getString("username"), 
       resultSet.getString("email"), 
       resultSet.getDate("birthdate"))); 
     } 
    } 

    return users; 
} 

,然後就處理它相應的業務/域對象,例如

List<User> users = userDAO.list(); 

if (!users.isEmpty()) { 
    int count = users.size(); 
    // ... 
} 
else { 
    // Help, no users? 
} 
+0

由於代碼示例的廣度,我選擇「接受」這一個和文檔鏈接。 – DVK 2009-11-29 05:15:44

6
while (rs.next()) { 
// process the row 
} 
+0

本答案#4。什麼abiout#1-3? :) – DVK 2009-11-28 23:11:30

5

從JavaDoc中ResultSet

ResultSet對象的光標 指向其當前數據行。 最初光標在第一行之前定位爲 。下一個方法 將光標移動到下一行,並且 ,因爲當對象中沒有更多行時 對象返回false時,它可以在while循環 中用於遍歷結果集。

您需要將ResultSet放置在一行上,例如,在嘗試讀取任何數據之前調用呼叫next()。如果對next()的呼叫返回false,則結果集爲空。

+0

這個答案#4。什麼abiout#1-3? :) – DVK 2009-11-28 23:12:07

+0

@DVK直到ResultSet被定位在一行上,調用'getString'沒有任何意義,所以它會引發異常(這適用於任何JDBC驅動程序)是合理的。我不確定'Resultset的'打開'標誌'是指什麼。 – 2009-11-28 23:30:40

+0

在Eclipse的調試器中,當檢查結果集時,「open」成員具有「false」值。這就是「ResultSet關閉」異常的原因(不是基礎原因,而是檢查的即時變量,用於在JDBC源中生成異常) – DVK 2009-11-29 05:14:17

1

對於此類的問題,你可能會使用這樣的

while(rs.next()) 
{ 
    String name=rs.getString("Name"); 
    int roll_no=Integer.parseInt(rs.getString("Roll")); 
} 
finally 
{ 
    try 
    { 
     rs.close(); 
     pst.close(); 
    } 
    catch(Exception ee) 
    { 
    } 
} 

Joptionpane.showmessahedialog(this,ee); 
+0

小心格式化帖子。我已格式化您的答案之一,檢查並格式化其他答案,如果有的話! – 2015-05-07 12:44:07

+0

thanx Paresh Mayani我是新來的這個網站。 – 2015-10-21 09:45:26

+0

無後顧之憂......繼續貢獻! – 2015-10-23 04:29:30

相關問題