Where to close java PreparedStatements and ResultSets?

后端 未结 13 2241
忘了有多久
忘了有多久 2020-11-29 02:26

Consider the code:

PreparedStatement ps = null;
ResultSet rs = null;
try {
  ps = conn.createStatement(myQueryString);
  rs = ps.executeQuery();
  // process         


        
13条回答
  •  长情又很酷
    2020-11-29 03:07

    In Java 7, you should not close them explicitly, but use automatic resource management to ensure that resources are closed and exceptions are handled appropriately. Exception handling works like this:

    Exception in try | Exception in close | Result
    -----------------+--------------------+----------------------------------------
          No         |        No          | Continue normally
          No         |        Yes         | Throw the close() exception
          Yes        |        No          | Throw the exception from try block
          Yes        |        Yes         | Add close() exception to main exception
                     |                    |  as "suppressed", throw main exception
    

    Hopefully that makes sense. In allows pretty code, like this:

    private void doEverythingInOneSillyMethod(String key)
      throws MyAppException
    {
      try (Connection db = ds.getConnection()) {
        db.setReadOnly(true);
        ...
        try (PreparedStatement ps = db.prepareStatement(...)) {
          ps.setString(1, key);
          ...
          try (ResultSet rs = ps.executeQuery()) {
            ...
          }
        }
      } catch (SQLException ex) {
        throw new MyAppException("Query failed.", ex);
      }
    }
    

    Prior to Java 7, it's best to use nested finally blocks, rather than testing references for null.

    The example I'll show might look ugly with the deep nesting, but in practice, well-designed code probably isn't going to create a connection, statement, and results all in the same method; often, each level of nesting involves passing a resource to another method, which uses it as a factory for another resource. With this approach, exceptions from a close() will mask an exception from inside the try block. That can be overcome, but it results in even more messy code, and requires a custom exception class that provides the "suppressed" exception chaining present in Java 7.

    Connection db = ds.getConnection();
    try {
      PreparedStatement ps = ...;
      try {
        ResultSet rs = ...
        try {
          ...
        }
        finally {
          rs.close();
        }
      } 
      finally {
        ps.close();
      }
    } 
    finally {
      db.close();
    }
    

提交回复
热议问题