我经常遇到这样的情况: -
try{
...
stmts
...
}
catch(Exception ex) {
...
stmts
...
} finally {
connection.close // throws an exception
}
最终还是需要一个try-catch块。
克服这个问题的最佳做法是什么?
答案 0 :(得分:24)
编写一个SQLUtils
类,其中包含捕获并记录此类异常的static closeQuietly
方法,然后根据需要使用。
你最终得到的内容如下:
public class SQLUtils
{
private static Log log = LogFactory.getLog(SQLUtils.class);
public static void closeQuietly(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing connection.", e);
}
}
public static void closeQuietly(Statement statement)
{
try
{
if (statement!= null)
{
statement.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing statement.", e);
}
}
public static void closeQuietly(ResultSet resultSet)
{
try
{
if (resultSet!= null)
{
resultSet.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing result set.", e);
}
}
}
您的客户端代码将类似于:
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try
{
connection = getConnection();
statement = connection.prepareStatement(...);
resultSet = statement.executeQuery();
...
}
finally
{
SQLUtils.closeQuietly(resultSet);
SQLUtils.closeQuietly(statment);
SQLUtils.closeQuietly(connection);
}
更新:自Java 7以来,各种JDBC接口扩展java.lang.AutoCloseable
,而上述代码回答了原始问题,如果您直接针对JDBC API编写代码,它可以现在结构化:
try (
Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement(...);
ResultSet resultSet = statement.executeQuery()
)
{
...
}
答案 1 :(得分:12)
正如其他人所提到的,静态closeQuietly
实用程序是可行的方法。要添加的一件事 - 如果您处于java.io
而非java.sql
的世界中,那么就会有一个有用的界面来实现此目的 - java.io.Closeable
java.io
中的所有数据源和接收器都实现了此接口 - 所有流,通道,编写器和读取器。这样,您可以创建一个实用程序来处理相同的“close()”异常问题,而无需许多重载版本。
e.g。
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
答案 2 :(得分:10)
我通常这样做:
try {
try {
..
stmts
...
}
finally {
connection.close():
}
} catch (Exception ex) {
..
stmts
..
}
当我没有使用照顾这个管道的库时,我通常只使用它。
正如Imagist指出的那样,这在技术上与最终将在捕获之前运行的相同,但我认为它解决了您试图解决的问题。
答案 3 :(得分:4)
Commons-io还为输入流提供了closeQuietly()。我一直在使用它。它使您的代码更具可读性。
答案 4 :(得分:1)
不要犹豫再试一次......最后赶上。
答案 5 :(得分:1)
在Java 10中,您可以写:
public void java10() throws SQLException {
try (var connection = Connections.openConnection();
var callableStatement = connection.prepareCall("my_call");
var resultSet = callableStatement.executeQuery()) {
while (resultSet.next()) {
var value = resultSet.getString(1);
System.out.println(value);
}
}
}
在Java 7,8和9中,你可以写:
public void java7() throws SQLException {
try (Connection connection = Connections.openConnection();
CallableStatement callableStatement = connection.prepareCall("my_call");
ResultSet resultSet = callableStatement.executeQuery()) {
while (resultSet.next()) {
String value = resultSet.getString(1);
System.out.println(value);
}
}
}
在Java 6中,您需要编写所有这些行:
public void java6() throws SQLException {
Connection connection = Connections.openConnection();
try {
CallableStatement callableStatement = connection.prepareCall("my_call");
try {
ResultSet resultSet = callableStatement.executeQuery();
try {
while (resultSet.next()) {
String value = resultSet.getString(1);
System.out.println(value);
}
} finally {
try {
resultSet.close();
} catch (Exception ignored) {
}
}
} finally {
try {
callableStatement.close();
} catch (Exception ignored) {
}
}
} finally {
try {
connection.close();
} catch (Exception ignored) {
}
}
}
答案 6 :(得分:0)
一般来说,除了记录关闭资源时发生的异常,你不想做任何事情,因此它应该真正进入自己的try / catch。然而,这是经常会发生的通用代码,所以不要重复自己,并将关闭置于静态方法中(如Nick Holt建议的那样),这样你就不会在同一个方法中使用两个try / catch项,使代码更易于阅读和遵循。
答案 7 :(得分:0)
Google Guava库中还有方便的Closeables#closeQuitely方法 - 它可以用于任何Closeable
答案 8 :(得分:0)
我们可以尝试阻止,最后是bock并稍后阻止阻塞吗?
答案 9 :(得分:-1)
请记住..最后总是通过try或catch来执行..