gpt4 book ai didi

java - JDBC 驱动程序在空 ResultSet 上抛出 "ResultSet Closed"异常

转载 作者:IT王子 更新时间:2023-10-29 06:21:03 33 4
gpt4 key购买 nike

我在 SQLite 的 JDBC 驱动程序中遇到问题。

我正在使用 SELECT 语句执行查询。

如果我得到一个空的 ResultSet(0 行),那么我会在调用 getString(1) 时看到抛出的“Closed ResultSet”异常。

在没有太多 JDBC 经验的情况下,我的理论(我无法通过 JavaDocs 确认 ResultSet)是

  • getString(1) 不适用于空(零行)结果集(设计或由于错误)
  • ResultSet 的“打开”标志在零行上设置为 false(同样,设计或错误)

我看到了这个bug report但不确定是否相关。

我的问题是:

  1. 上述理论是否正确?
  2. 这是一个错误吗?特征? (如果是这样,有人可以指出文档吗?)
  3. 它是特定于 SQLIte 的 JDBC 还是所有 JDBC 驱动程序中的通用 ResultSet
  4. 做这样的事情的正确方法是什么?

对于 #4,我的解决方案是在 executeQuery() 之后立即调用 isFirst() 来检查结果集中是否有任何行。这是最佳实践方法吗?

(我也可以简单地选择一个插入的计数,因为我真的不需要结果集,只需要零-非零标志,但如果我确实关心选择的结果,我想知道正确的做法)

谢谢!

最佳答案

无论是否为空,但执行以下操作总是错误:

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?
}

关于java - JDBC 驱动程序在空 ResultSet 上抛出 "ResultSet Closed"异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1813858/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com