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

问题描述 投票:30回答:10

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

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

最后还需要一个try-catch块。

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

java exception-handling try-catch-finally
10个回答
25
投票

编写一个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
投票

只记得..终于总是通过try或catch来执行..


12
投票

正如其他人所提到的,静态closeQuietly实用程序是可行的方法。有一点要补充 - 如果你在java.io而不是java.sql的世界,那么就有一个有用的界面正是为了这个目的 - java.io.Closeable

java.io中的所有数据源和接收器都实现了这个接口 - 所有流,通道,编写器和读取器。这样,您可以创建单个实用程序来处理相同的“close()”异常问题,而无需许多重载版本。

EG

public class IoUtils {

  public static closeQuietly (Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException logAndContinue) {
      ...
    }
  }

}

10
投票

我通常这样做:

try {
    try {
        ..
        stmts
        ...
    }
    finally {
       connection.close():
    }
} catch (Exception ex) {
     ..
     stmts
     ..    
}

我通常只在我没有使用照顾这个管道的库时才使用它。

正如Imagist指出的那样,这在技术上与最终将在捕获之前运行的相同,但我认为它解决了您试图解决的问题。


4
投票

Commons-io还为输入流提供了closeQuietly()。我一直在使用它。它使您的代码更具可读性。


1
投票

不要犹豫再试一次......最后赶上。


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) {
        }
    }
}

0
投票

一般来说,除了记录关闭资源时发生的异常,你不想做任何事情,所以它应该真正进入自己的try / catch。然而,这是经常会发生的通用代码,所以不要重复自己,并将关闭置于静态方法中(如Nick Holt建议的那样),这样你就不会在同一个方法中使用两个try / catch项,使代码更易于阅读和遵循。


0
投票

Google Guava库中还有方便的Closeables #closeQuitely方法 - 它可以用于任何Closeable


0
投票

我们可以尝试阻止,最后是bock,然后阻止阻塞吗?

© www.soinside.com 2019 - 2024. All rights reserved.