【问题标题】:The correct way to use JDBC resourcesJDBC资源的正确使用方式
【发布时间】:2014-04-17 16:07:44
【问题描述】:

即使在 Java 7 中,我也经常看到这样的代码

    Connection c = null;
    PreparedStatement s = null;
    try {
        c = dataSource.getConnection();

        String sql = "insert into table (column1, column2) values (?, ?);
        s = c.prepareStatement(sql);
        int i = 1;
        s.setString(i++, "111");
        s.setString(i++, "222");

        s.execute();

    } catch (SQLException e) {
        log.error("failed to insert", e);
    } finally {
        DbUtils.close(s, c); // closes s and c with no questions
    }

但根据规范,当连接关闭时,所有语句和结果集都会被释放。

我听说 JDBC 驱动程序有可能不遵守 JDBC API 的规则,老方法更好。我的问题是听听对此的看法。代码看起来更好,但如果它很危险怎么办? 在我看来,最喜欢的方法是在此处使用 try-with-resources。够安全吗?

【问题讨论】:

  • “可以吗?”是个什么样的问题?你自己说过:“尝试资源”是更好的处理方式。
  • 听说 JDBC 驱动程序有可能不按 JDBC API 的规则运行,老办法更好。我的问题是听听对此的看法。代码看起来更好,但如果它很危险怎么办?
  • 嗯,这就是您应该在问题中提出的内容。
  • @FedorovMikhail '旧方法更好'?我认为这表明缺乏对 try-with-resources 工作原理的理解,因为从技术上讲,try-with-resources 可以完成您的代码所做的工作,除了较少的样板文件和实际异常反馈(如果出现任何问题)。

标签: java jdbc try-with-resources


【解决方案1】:

资源是程序完成后必须关闭的对象。因此您不必在finally块中手动关闭对象

 String sql = "insert into table (column1, column2) values (?, ?);
    try(Connection  c = dataSource.getConnection();
    PreparedStatement s = c.prepareStatement(sql);) {


        int i = 1;
        s.setString(i++, "111");
        s.setString(i++, "222");

        s.execute();

    } catch (SQLException e) {
        log.error("Failed to insert transaction", e);
    } 

【讨论】:

    【解决方案2】:

    您应该始终释放/关闭您使用的资源,例如 ResultSet、Statement、Connection。这应该在 finally 块中完成。您在此处粘贴的 sn-p 看起来不错(只要 s 和 c 在 QuietDb 中关闭)。

    【讨论】:

      【解决方案3】:

      虽然closing a Connection will close all Statements associated with it,但在大多数数据库中,您可以同时为任何一个Connection 打开多少Statements。

      如果您不关闭Statements,则会增加ORA-01000: maximum open cursors exceeded 等错误的可能性。

      如果您关闭Statementsthey also close their ResultSets,那么您不必同时关闭这两个。

      【讨论】:

      • 这是假设实现行为良好,但并非总是如此。完成后最好显式关闭资源。
      【解决方案4】:

      使用try-with-resources,您的代码可以重写为:

      try (
          Connection c = dataSource.getConnection();
          PreparedStatement s = c.prepareStatement("insert into table (column1, column2) values (?, ?)");
      ) {
          int i = 1;
          s.setString(i++, "111");
          s.setString(i++, "222");
      
          s.execute();
      } catch (SQLException e) {
          log.error("failed to insert", e);
      }
      

      这保证了语句和连接都被关闭(即使关闭语句会引发异常!)。唯一的区别可能是关闭时可能会抛出异常,因为我不知道您的DbUtils.close 是否会吞下异常。

      一般而言,try-with-resources 提供了更简洁的代码,并且更能确保资源以正确的顺序正确关闭,而无需太多样板。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-10
        • 2017-02-18
        相关资源
        最近更新 更多