在Java中关闭数据库连接的合适方法是什么?
我试图关闭数据库连接。比如说有点混乱
ResultSet rs = null
我是否必须靠近它
rs.close();
要么
DatabaseUtil.closeResultSet(rs);
那些有什么区别?
这些方法只关闭ResultSet
。 您仍然必须关闭所有Statement
和Connection
实例。 我建议在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
。 因为它占用了内存和资源,所以在完成它们之后需要关闭它们,否则垃圾收集器将会这样做,它只会回收内存。 - 您不再需要时关闭
PreparedStatement
或Statement
。 关闭语句将关闭关联的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) { }