简体   繁体   中英

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?

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.

The jdbc api tells us that closing the connection will close result sets and statements. Closing statements will close the result set. But I always close every result set and every statement myself because I ran into problems not doing so. Just use the close method provided by you result set, statement and connection.

I think the best way is do everything within a try-with-resources

try(conn=openConnection()){
  try(rs=conn.getResultSet()){
  }
}

So that you be entirely sure the resources will be properly closed at the end.

Both ways works, but I prefer the first rs.close(); , without forgeting to check if rs is not null and to enclose your call by a try..catch statement so you have to close your connection in the finaly block even if Java7 close all for you.

check Java / JDBC: Best design pattern to close database connection when exception occurs

Those methods only close the ResultSet . You still have to close all Statement and Connection instances. I recommend doing so in a finally block. Something like,

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
  conn = getConnection();
  stmt = conn.prepareStatement(sql);
  stmt.setString(1, "Hello"); 
  rs = stmt.executeQuery();
  while (rs.next()) {
    // ...
  }
} catch (SQLException se) {
  se.printStackTrace();
} finally {
  if (rs != null) {
    try {
      rs.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  if (stmt != null) {
    try {
      stmt.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  if (conn != null) {
    try {
      conn.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

If you use my Close utility the finally block could be,

} finally {
  Close.close(rs, stmt, conn);
}

Normal code would look like this:

Connection connection = null;
PreparedStatement stmt = null;
ResultSet rs = null;
ResultSet rs2 = null;
try {
  connection = getConnection();
  stmt = connection.prepareStatement("...");

  stmt.setString(":foobar", "Foobar");
  rs = stmt.execute ... ; // I don't remember the method return ResultSet

  while (rs.next()) {
    ...
  }

  stmt.setString(":foobar", "Barfoo");
  rs2 = stmt.execute ... ; 


} finally {
  if (null != rs2) try {rs2.close();} catch (Exception e)
  if (null != rs) try {rs.close();} catch (Exception e) {...}
  if (null != stmt) try {stmt.close();} catch (Exception e) {...}
  if (null != connection) try {connection.close();} catch (Exception e) {...}
}

Or, in Java 7, using the try-with-resources (the previous code is almost the same):

try (Connection connection = getConnection();
     PreparedStatement stmt = connection.prepareStatement("...")) {

  stmt.setString(":foobar", "Foobar");
  try (ResultSet rs = stmt.executeQuery()) {
    while (rs.next()) {
        ...
    }
  }
  stmt.setString(":foobar", "Barfoo");
  try (ResultSet rs2 = stmt.executeQuery()) {
    while (rs2.next()) {
        ...
    }
  }
}

The difference is simple:

  • you close the ResultSet - to free the resource associated. In this example, I used a PreparedStatement : you could have parameters, hence different ResultSet . Because it takes memory and resources, you need to close them after you are done with them, otherwise that the garbage collector that will do that, and it will do it only to reclaim memory.
  • you close the PreparedStatement or Statement when you no longer need it. Closing the statement close the associated ResultSet .
  • you close the Connection when you no longer need it. Closing the connection close the Statement s (and their ResultSet ).

Depending on your need (eg: a batch versus a web server), you might not have to close the connection at it would be when Java exit, but it is better to free resources when you no longer need them (whether them being JDBC resources or file resources...).

Closing the resultSet doesn't close the database connection. We should close the connection as like given below. Before closing the connection you should close the other instance like ResultSet, PreparedStatement and Statement instances.

for example

 Connection con = DBUtils.getConnection();
 ....
 PreparedStatemet pstmt = con.getPreparedStatement();
 ResultSet rs = pstmt.execute();

 while(rs.next())
 {
 }

// Once you done the ResultSet... It's time to close/release the Instances.

    if (resultSet != null) {
    try {
    resultSet.close();
    resultSet = null;
    } catch (SQLException e) {
      // ignore the exceptions.
    }
    }

    // Close the Prepared Statement
    if(theStatement != null)
    {
    try
    {
    theStatement.close();
    theStatement = null;
    }
    catch(Exception ignored)
    {
    }

// Close the Connection
    if(theConnection != null)
    {
    try
    {
    theConnection.close();
    theConnection = null;
    }
    catch(Exception ignored)
    {
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM