关闭结果集不会关闭数据库连接。您需要单独执行此操作。
通常您会希望像这样关闭资源:
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
log.info("closing resultset caused exception", e);
}
}
如果这是您的 DatabaseUtil 所做的,那将是更可取的。
使用 try-with-resources 会产生更漂亮的代码,但请注意,一种极端情况的行为是非常不同的。如果在关闭结果集时抛出异常(在其他所有操作都没有问题之后),那么上面的代码不会传播它,因此它不会阻止其余事务的完成。但是,如果您使用 try-with-resources,则 close 方法抛出的异常将被传播。关闭结果集或语句时抛出的异常只是关于释放数据库资源(无论如何最终都会被释放,这不是危机),它并不表示任何数据问题,而且似乎不是破坏数据库的理由手术。
您应该在关闭结果集后关闭数据库连接。确保使用 finally 块,以便无论抛出什么异常(包括关闭语句或结果集时抛出的异常)都会关闭连接。
code in this question 是 not 如何做到这一点的一个例子(很可能 OP 想要最小化示例中的样板,因为关闭事情不是问题的重点,所以它可能是为了保持简短,而不是因为OP不知道不这样做),它展示了现实生活中发生的常见错误:
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;
}
}
如果 statement.close 抛出 SQLException,那么 finally 块中的以下行将永远不会被调用,连接不会被关闭,并且数据库连接将一直处于未使用状态,直到超时。这可能看起来不错,因为它只是一个连接,但是每个其他连接可能会看到相同的行为,并且在适当的情况下,您可以通过这种方式关闭整个应用程序(丢弃所有数据库连接)。请参阅 Michael Nygard's book Release It! 了解一个故事,该故事描述了一个非常昂贵且痛苦的企业应用程序中断,该中断可追溯到完全像这样的代码。
不得不剪切和粘贴这个关闭资源的代码是丑陋的,引入类似模板方法的东西来传递结果集映射器将是一种改进,这样关闭只在一个地方完成。但这会让您走上重塑 spring-jdbc 的道路,它已经为您完成了所有这些工作。