2009-11-28 73 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

相关问题