【发布时间】:2015-12-18 00:30:21
【问题描述】:
为什么数据库连接经常在两个位置关闭,一次是在使用后直接关闭,其次是在 finally 块中使用 null 检查以防止它们被关闭两次。使用 finally 块还不够吗? finally 块将在每种情况下执行。
这是Apache-Tomcat JNDI Datasource HOW-TO 的官方示例。他们指出,在任何情况下都必须关闭连接。我想知道为什么在主 try {} 块的末尾使用 finally 块作为关闭命令是不够的,这似乎是多余的。
Connection conn = null;
Statement stmt = null; // Or PreparedStatement if needed
ResultSet rs = null;
try
{
conn = ... get connection from connection pool ...
stmt = conn.createStatement("select ...");
rs = stmt.executeQuery();
... iterate through the result set ...
rs.close ();
rs = null;
stmt.close ();
stmt = null;
conn.close (); // Return to connection pool
conn = null; // Make sure we don't close it twice
}
catch (SQLException e)
{
... deal with errors ...
}
finally
{
// Always make sure result sets and statements are closed,
// and the connection is returned to the pool
if (rs != null)
{
try
{
rs.close ();
}
catch (SQLException ignore)
{
}
rs = null;
}
if (stmt != null)
{
try
{
stmt.close ();
}
catch (SQLException ignore)
{
}
stmt = null;
}
if (conn != null)
{
try
{
conn.close ();
}
catch (SQLException ignore)
{
}
conn = null;
}
}
我想写得更短:
Connection conn = null;
Statement stmt = null; // Or PreparedStatement if needed
ResultSet rs = null;
try
{
conn = ... get connection from connection pool ...
stmt = conn.createStatement ("select ...");
rs = stmt.executeQuery();
... iterate through the result set ...
}
catch (SQLException e)
{
// ... deal with errors ...
}
finally
{
// Always make sure result sets and statements are closed,
// and the connection is returned to the pool
try
{
if (rs != null)
rs.close ();
if (stmt != null)
stmt.close ();
if (conn != null)
conn.close ();
}
catch (SQLException ignore)
{
}
}
【问题讨论】:
-
这是我第一次看到这个。我遇到的所有示例都只在 finally 块中进行。我不认为这是一种非常流行的做法。我认为它增加了代码的开销和复杂性。
-
或者更短的
try-with-resources;) 但是,是的,这个例子似乎过于复杂了。 -
如果
rs.close()在您的代码中抛出异常怎么办?那么stmt和conn将不会被关闭。 -
对!应该将 Apache 示例中的所有三个关闭命令放在三个独立的 try-catch 块中。
-
Tomcat 示例代码质量很差,但您的代码没有改进。 Java 7 的正确解决方案是使用 try-with-resources。