我在SQLite的JDBC驱动程序中遇到问题。
我正在使用SELECT语句执行查询。
如果我得到一个空的ResultSet
(0行),那么我会在调用getString(1)
时看到一个“Closed ResultSet”异常。
如果没有先前的JDBC经验,我的理论(我无法通过JavaDocs确认ResultSet
)是
getString(1)
不适用于空(零行)结果集(按设计或由于错误)ResultSet
的“open”标志在零行上设置为false
(再次,按设计或错误)我看到了bug report,但我不确定它是否相关。
我的要求是:
ResultSet
?对于#4,我的解决方案是在isFirst()
之后立即使用executeQuery()
调用来检查结果集中是否有任何行。这是最佳做法吗?
(我也可以简单地选择一个计数insetad因为我不需要一个结果集,只有零非零标志,但我想知道正确的事情,如果我关心选择的结果)
谢谢!
答案 0 :(得分: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;
}
然后在business / domain对象中相应地处理它,例如
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;
}
然后在business / domain对象中相应地处理它,例如
List<User> users = userDAO.list();
if (!users.isEmpty()) {
int count = users.size();
// ...
}
else {
// Help, no users?
}
答案 1 :(得分:6)
while (rs.next()) {
// process the row
}
答案 2 :(得分:5)
来自ResultSet的JavaDocs:
ResultSet对象维护游标 指向其当前的数据行。 最初定位光标 在第一行之前。下一个方法 将光标移动到下一行,然后 因为它在那里返回false 在ResultSet中不再有行 对象,它可以在while循环中使用 迭代结果集。
您需要将ResultSet
放在一行,例如在尝试读取任何数据之前,通过调用next()
来调用。如果对next()
的调用返回false
,则结果集为空。
答案 3 :(得分: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);