尝试捕获 - 最后再尝试捕获

时间:2009-08-26 16:03:17

标签: java exception-handling try-catch-finally

我经常遇到这样的情况: -

try{ 
     ...
     stmts
     ...
} 
catch(Exception ex) {
     ... 
     stmts
     ... 
} finally {
     connection.close // throws an exception
}

最终还是需要一个try-catch块。

克服这个问题的最佳做法是什么?

10 个答案:

答案 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来执行..