Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
432 views
in Technique[技术] by (71.8m points)

jdbc - What is the suitable way to close the database connection in Java?

I tried to close the DB connection.But had a bit of confusion, say

ResultSet rs = null 

Whether I have to it close by

rs.close();

Or

DatabaseUtil.closeResultSet(rs);

What is difference between those?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Closing the resultSet doesn't close the database connection. You need to do that separately.

Typically you would want to close a resource like this:

if (resultSet != null) {
     try {
         resultSet.close();
     } catch (SQLException e) {
         log.info("closing resultset caused exception", e);
     }
}

If that is what your DatabaseUtil does, then that would be preferable.

Using try-with-resources results in prettier code, but be aware that the behavior for one edge case is very different. If an exception is thrown while closing the resultSet (after everything else has proceeded without a problem) then with the above code it is not propagated, so it doesn't stop the rest of the transaction from completing. However, if you use try-with-resources, the exception thrown by the close method will get propagated. The exception thrown while closing a resultSet or statement is only about freeing database resources (that will get freed eventually anyway, it's not a crisis), it doesn't indicate any data problems and it doesn't seem like a reason to torpedo the database operation.

You should close the database connection after closing the resultSet. Make sure you use a finally block so that closing the connection happens regardless of what exceptions are thrown (including exceptions thrown while closing statements or resultSets).

The code in this question is one example of how not to do it (it's likely the OP wanted to minimize the boilerplate in the example, since closing things is not the focus of the question, so it may be this way in order to be kept short, not because the OP doesn't know not to do this), it demonstrates a common error that happens in real life:

Class Class1<T>
{
  public T getColumn(DataSource ds)
  {
    T value = null;
    Connection con = null;
    Statement st = null;

    try
    {
      con = ds.getConnection();
      st = con.createStatement();
      ResultSet rs = st.executeQuery("select 1 from dual");
      rs.next();
      Object o = rs.getObject(1); // I want an Integer but a BigDecimal is created!
      value = (T) o; // ClassCastException here!
    }
    finally
    {
      if (st != null) { st.close(); }
      if (con != null) { con.close(); }
    }

    return i;
  }
}

If the statement.close throws a SQLException, then the following line in the finally block never gets called, the connection will not get closed, and the database connection will hang around unused until it times out. This may not seem bad since it's only one connection, but every other connection may see the same behavior and under the right circumstances you can bring your whole application down this way (throwing away all your database connections). See Michael Nygard's book Release It! for a story describing a very expensive and painful enterprise application outage that was traced back to code exactly like this.

Having to cut-and-paste this resource-closing code is ugly, it would be an improvement to introduce something like a template method that passes in a resultset mapper, so that the closing is done in only one place. But that puts you on the road to reinventing spring-jdbc, which has already done all this for you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...