【问题标题】:Trying to query database using PreparedStatement, ResultSet is coming back closed when it ought not to尝试使用 PreparedStatement 查询数据库,结果集在不应该关闭时返回关闭
【发布时间】:2012-01-18 18:40:20
【问题描述】:

我正在尝试使用准备好的语句查询我的数据库。最初,我有这个:

public ResultSet preparedQueryContactsWhereAccount(String accountName) throws SQLException {
    PreparedStatement statment = null;
    ResultSet rs = null;
    String statString = "SELECT * FROM contacts WHERE account_name = ?";

    try {
        statment = mConn.prepareStatement(statString);
        statment.setString(1, accountName);
        rs = statment.executeQuery();
    } catch(SQLException e) {
        e.printStackTrace();
    }
    if(statment != null) {
        statment.close();
    }
    return rs;
}

但是,这将返回一个封闭的 ResultSet。我做了一些阅读,发现有时当一个语句关闭时,它的 ResultSets 也可以关闭。所以我尝试了这个:

public MasterEntry preparedQueryContactsWhereAccount(String accountName, MasterEntry entry) throws SQLException, IllegalAccessException {
    PreparedStatement prepStat = null;
    ResultSet rs = null;
    String statString = "SELECT * FROM contacts WHERE account_name = ?";

    try {
        prepStat = mConn.prepareStatement(statString);
        prepStat.setString(1, accountName);
        rs = prepStat.executeQuery();
    } catch(Exception e) {
        e.printStackTrace();
        System.err.println("Statement failed.");
    }
    if(rs.isClosed()) {
        System.out.println("fail");
        throw new IllegalAccessException("closed");
    }
    else {
        entry.setmFirstName(rs.getString("first_name"));
        entry.setmLastName(rs.getString("last_name"));
        entry.setmEmail(rs.getString("email_address"));
        rs.close();
        prepStat.close();
    }
    return entry;

}

只是稍微重新组织了流程,以便 ResultSet 数据都可以在方法内部处理。这会引发 IllegalAccessException,您可以在那里看到,ResultSet 已关闭。

我尝试以更简单的方式执行相同的查询(不安全且无法处理撇号等字符):

public ResultSet makeQuery(String query) {
    ResultSet rs = null;
    try {
        rs = mStat.executeQuery(query);
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Problem in query: " + query);
    }
    return rs;
}

查询等于"SELECT * FROM contacts WHERE account_name = '" + accountName + "'"

与我在preparedQuery 方法中使用的相同的accountName 字符串。这种方法可以正常工作,当然任何带有撇号的 accountName 都会失败。我真的很想用一个准备好的声明来做到这一点,但我就是想不通。有什么建议吗?非常感谢。

【问题讨论】:

    标签: java sql jdbc prepared-statement resultset


    【解决方案1】:

    看起来您的代码很好,但是您缺少 rs.next() 命令。您正在尝试读取尚未设置为特定行的结果集,因此您会收到 IllegalStateException。

    【讨论】:

      【解决方案2】:

      我建议你不要这样做。

      您应该立即循环遍历它并提取所有结果并将它们交给其他东西,而不是返回您的 ResultSet。然后它应该被关闭。

      传递诸如语句、结果集和连接之类的东西最终会导致资源泄漏,更不用说在代码中创建不必要的复杂性以试图避免这些泄漏。它们都应该在 finally 块中打开、使用并立即关闭,以避免任何泄漏。从此类方法返回的任何内容都不应与具有生命周期和相关资源的某些 DB 对象绑定。

      你不必接受这个建议,但我真的相信如果你这样做,你的生活会更轻松。

      【讨论】:

        【解决方案3】:

        除非您已经尝试过它们并且它们没有您需要的功能,否则我建议您不要直接使用 JDBC。相反,只需获取 Hibernate、iBatis(已退役,但仍可使用)或 myBatis(继续使用 iBatis)并让它们处理 JDBC 内容。与普通项目相比,这些 ORM 工具可能会更好地管理资源。

        【讨论】:

          猜你喜欢
          • 2019-08-08
          • 2014-12-29
          • 2017-09-30
          • 2015-02-26
          • 2015-02-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多