resultSet.next()返回false,即使填充了表

Nat*_*ios 4 java sqlite jdbc resultset

我有一些函数可以帮助从数据库中检索对象.

public User getUser(int beamID) throws NoSuchUserException {
    return userFromResultSet(getUserResultSet(beamID));
}


private ResultSet getUserResultSet(int beamID) {
    try(Connection conn = dataSource.getConnection()) {

        // queries.getUserByBeamID() returns "SELECT * FROM user WHERE beamID=?"
        PreparedStatement stmt = conn.prepareStatement(queries.getUserByBeamID());

        stmt.setInt(1, beamID);
        System.out.println(stmt.toString());
        return stmt.executeQuery();

    } catch (SQLException e) {
        e.printStackTrace();
        throw new IllegalStateException();
    }
}

private User userFromResultSet(ResultSet resultSet) {
    try {
        boolean next = resultSet.next();  // Debugger tells me this is false.
        if (!next)
            throw new NoSuchUserException();

        User user = new User(this,
             resultSet.getInt("beamID"),
             resultSet.getString("name"),
             resultSet.getInt("points"),
             resultSet.getInt("time")
        );

        if (resultSet.next())
            throw new IllegalStateException("Duplicate user entries exist - database integrity compromised!");

        return user;
    } catch (SQLException e) {
        e.printStackTrace();
        throw new IllegalStateException();
    }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,我知道数据确实存在有两个原因:

  • 如果该条目不存在,我的程序会尝试创建该条目,但尝试该条目会产生错误,即不遵循唯一约束.

  • 在我的SQLite DB浏览器中运行查询工作正常:

查询返回结果,应该如此.

我非常怀疑这是未提交数据的问题,因为这是一个基于文件的数据库,并且使用文本编辑器打开该文件会显示数据中用户名的实例.

Tim*_*sen 7

仔细看看你在这做什么:

try (Connection conn = dataSource.getConnection()) {
    PreparedStatement stmt = conn.prepareStatement(queries.getUserByBeamID());

    stmt.setInt(1, beamID);
    System.out.println(stmt.toString());
    return stmt.executeQuery();
} catch (SQLException e) {
    e.printStackTrace();
    throw new IllegalStateException();
}
Run Code Online (Sandbox Code Playgroud)

我相信try在表达式完成执行之后,这是try-with-resources的合同,以保证关闭子句中指定的资源.我相信结果集也在try块的末尾被关闭,因此调用next()返回false,因为没有任何东西.

我编写代码的方法是填充块User内的POJO try,并返回一个User对象而不是返回结果集:

private User getUserResultSet(int beamID) {
    User user = null;
    try (Connection conn = dataSource.getConnection()) {
        PreparedStatement stmt = conn.prepareStatement(queries.getUserByBeamID());

        stmt.setInt(1, beamID);

        ResultSet rs = stmt.executeQuery();
        rs.next();
        user = new User(this,
            rs.getInt("beamID"),
            rs.getString("name"),
            rs.getInt("points"),
            rs.getInt("time")
        );

    } catch (SQLException e) {
        e.printStackTrace();
        throw new IllegalStateException();
    }

    return user;
}
Run Code Online (Sandbox Code Playgroud)

现在你关注的问题比以前更好了.如果连接,结果集等出现问题,它将在处理这些事情的实际代码中处理.如果发生异常或其他错误,null将返回用户对象,您应该更新代码以处理这种可能性.