在Java中关闭数据库连接的合适方法是什么?

我试图关闭数据库连接。比如说有点混乱

ResultSet rs = null 

我是否必须靠近它

 rs.close(); 

要么

 DatabaseUtil.closeResultSet(rs); 

那些有什么区别?

这些方法只关闭ResultSet 。 您仍然必须关闭所有StatementConnection实例。 我建议在finally块中这样做。 就像是,

 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(); } } } 

如果你使用我的Close实用程序 ,finally块可能是,

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

关闭resultSet不会关闭数据库连接。 你需要单独做。

通常,您希望关闭这样的资源:

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

如果这是您的DatabaseUtil所做的,那么这将是更可取的。

使用try-with-resources会产生更漂亮的代码,但要注意一个边缘情况的行为是非常不同的。 如果在关闭resultSet时抛出exception(在其他所有操作都没有问题之后),那么使用上面的代码就不会传播它,因此它不会阻止事务的其余部分完成。 但是,如果使用try-with-resources,则close方法抛出的exception将被传播。 关闭resultSet或语句时抛出的exception只是释放数据库资源(无论如何最终都会被释放,这不是危机),它并不表示任何数据问题,并且它似乎不是破坏数据库的理由操作。

关闭resultSet后应关闭数据库连接。 确保使用finally块,以便无论抛出什么exception(包括关闭语句或resultSets时抛出的exception),都会关闭连接。

这个问题中的代码是如何这样做的一个例子(可能是OP希望最小化示例中的样板,因为关闭事物不是问题的焦点,所以它可能是这样的,以便保持简而言之,不是因为OP不知道不这样做,它表明了现实生活中常见的错误:

 Class Class1 { 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; } } 

如果statement.close抛出一个SQLException,那么finally块中的以下行永远不会被调用,连接将不会被关闭,并且数据库连接将在未使用之前挂起。 这可能看起来不是很糟糕,因为它只有一个连接,但是每个其他连接可能会看到相同的行为,并且在适当的情况下,您可以以这种方式将整个应用程序放下(丢弃所有数据库连接)。 见Michael Nygard的书Release It! 一个故事描述了一个非常昂贵和痛苦的企业应用程序中断,可以追溯到完全像这样的代码。

必须剪切和粘贴这个资源关闭代码是丑陋的,引入类似于传递结果集映射器的模板方法会有所改进,因此关闭只在一个地方完成。 但这会让你走上重塑spring-jdbc的道路,这已经为你完成了所有这些。

jdbc api告诉我们关闭连接将关闭结果集和语句。 结束语句将关闭结果集。 但是我总是关闭每一个结果集和每一个声明,因为我遇到的问题不是这样做的。 只需使用结果集,语句和连接提供的close方法。

我认为最好的方法是在资源试用中做所有事情

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

这样您就可以完全确定资源最终会被正确关闭。

两种方式都有效,但我更喜欢第一个rs.close(); ,没有伪造检查rs是否为空并且通过try..catch语句包含您的调用,因此即使Java7为您关闭所有内容,您也必须在最终块中关闭连接。

检查Java / JDBC:发生exception时关闭数据库连接的最佳设计模式

普通代码如下所示:

 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) {...} } 

或者,在Java 7中,使用try-with-resources (以前的代码几乎相同):

 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()) { ... } } } 

区别很简单:

  • 您关闭ResultSet – 释放相关的资源。 在这个例子中,我使用了PreparedStatement :你可以有参数,因此不同的ResultSet 。 因为它占用了内存和资源,所以在完成它们之后需要关闭它们,否则垃圾收集器将会这样做,它只会回收内存。
  • 您不再需要时关闭PreparedStatementStatement 。 关闭语句将关闭关联的ResultSet
  • 在不再需要时关闭Connection 。 关闭连接会关闭Statement (及其ResultSet )。

根据您的需要(例如:批处理与Web服务器),您可能不必在Java退出时关闭连接,但在不再需要资源时更好地释放资源(无论它们是否为JDBC资源)或文件资源……)。

关闭resultSet不会关闭数据库连接。 我们应该关闭连接,如下所示。 在关闭连接之前,您应该关闭另一个实例,如ResultSet,PreparedStatement和Statement实例。

例如

  Connection con = DBUtils.getConnection(); .... PreparedStatemet pstmt = con.getPreparedStatement(); ResultSet rs = pstmt.execute(); while(rs.next()) { } 

//完成ResultSet后……是时候关闭/释放实例了。

  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) { }