【问题标题】:Is a PreparedStatement left "open" if the reference is overwritten?如果引用被覆盖,PreparedStatement 是否保持“打开”状态?
【发布时间】:2012-12-20 15:30:09
【问题描述】:

假设我从Connection 对象中获得了PreparedStatement,然后我用另一个PreparedStatement 覆盖了引用。然后,后来,我close() 参考。第一个PreparedStatement(我失去了引用的那个)会保持开放吗?还是有一些协议或垃圾收集来处理这个问题?

例如:

PreparedStatement ps = connection.prepareStatement(MY_QUERY);
// do stuff
ps.execute();

ps = connection.prepareStatement(MY_OTHER_QUERY);
// do stuff
ps.execute();

ps.close();

第一个 PreparedStatement 对象(用于执行 MY_QUERY 的对象)是否保持打开状态?

【问题讨论】:

标签: java database-connection prepared-statement


【解决方案1】:

是的,PreparedStatement 将保持打开状态,直到它被垃圾收集*(如果有的话)。

这就是为什么你总是看到规则总是释放(关闭)你获得的外部资源

JDBC 资源(例如这个准备好的语句、连接、结果集)和 IO 资源(套接字、流等)是您在 Java 中需要手动管理的两种最常见的资源。

* 严格来说它可以finalize方法中被关闭,这可能稍微早于它被GCed,但之后> 它有资格获得 GC,但对于本次讨论,这已经足够接近了。

【讨论】:

  • 我认为您的最后一句话将 finally 块与 finalize 方法混淆了。
  • +1 如果我们对 java 7 中引入的资源块使用 try,PreparedStatement 将自动关闭。
  • @bowmore:当然。我很少使用finalize,甚至打错了。
  • 你的答案中的“(如果有的话)”是什么意思?有没有办法在垃圾收集后保持打开状态?或者你是说它可能永远不会被垃圾收集?
  • @Jeff:当相应的 Java 对象被垃圾回收时,可能没有正确释放外部资源。例如,如果我编写了一个使用本机代码分配文件句柄的类,并且没有编写了 finally 方法来关闭文件句柄,那么我的对象可能会被垃圾收集,但文件句柄将保持打开状态,有效地产生资源泄漏。另外:其他东西(例如连接)很可能会持有对 PreparedStatement 的引用,从而有效地防止它被 GC,直到连接本身可以被 GC。
【解决方案2】:

当对象最终被垃圾回收时,它将被关闭。由于您对垃圾收集过程几乎没有控制权,因此最好在完成语句后立即关闭它们。

来自Statement.close() 的文档:

立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待它自动关闭时发生。通常最好在使用完资源后立即释放资源,以避免占用数据库资源。

【讨论】:

    【解决方案3】:

    它将保持打开状态,并且不能保证在垃圾收集时它会关闭。这取决于实施。实现需要像 FileInputStream.finalize 那样覆盖 finalize

    "...确保在没有更多引用时调用此文件输入流的 close 方法。"

    但是 Connection.close 可以关闭 PreparedStatement,参见 Connection.close 的 API:

    "..立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们自动释放.."

    但前提是它不是池连接。

    【讨论】:

    • 那么如果准备PreparedStatementConnection 被关闭,它也会关闭所有那些(丢失的)PreparedStatement 对象?
    • 是的,DB 也会在关闭时释放会话/连接占用的所有资源。但池连接可能不是这种情况,因为它们忽略了 close()
    猜你喜欢
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多