Подтвердить что ты не робот

Try-catch-finally, а затем снова попытайтесь поймать

Я часто сталкивался с ситуациями вроде: -

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

который по-прежнему нуждается в блоке try-catch внутри.

Какова наилучшая практика для преодоления этого?

4b9b3361

Ответ 1

Напишите класс SQLUtils который содержит static closeQuietly методы 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 и хотя приведенный выше код отвечает на первоначальный вопрос, если вы пишете код непосредственно для API JDBC, теперь его можно структурировать:

try (
  Connection connection = getConnection();
  PreparedStatement statement = connection.prepareStatement(...);
  ResultSet resultSet = statement.executeQuery()
)
{
  ...
}

Ответ 2

Как уже упоминалось, статическая утилита closeQuietly - это путь. Добавим одно: если вы находитесь в мире java.io, а не java.sql, тогда для этого есть полезный интерфейс - java.io.Closeable

Все источники данных и приемники в java.io реализуют этот интерфейс - все потоки, каналы, писатели и читатели. Таким образом, вы можете создать единую утилиту для решения одной и той же проблемы исключения при закрытии(), не требуя много перегруженных версий.

например.

public class IoUtils {

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

}

Ответ 3

Я обычно делал это так:

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

Я обычно использовал это только тогда, когда я не использовал библиотеку, которая позаботилась об этом сантехнике для меня.

Как Imagist указывает, что это технически не то же самое, что, наконец, будет работать до улова, но я думаю, что он решает проблему, которую вы пытаетесь решать.

Ответ 4

Commons-io также имеет closeQuietly() для потоков ввода и вывода. Я использую его все время. Это делает ваш код более удобочитаемым.

Ответ 5

Не стесняйтесь использовать еще одну попытку... поймайте внутри наконец.

Ответ 6

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

Ответ 7

Как правило, вы не хотите делать ничего больше, чем регистрировать исключение, которое происходит при закрытии ресурса, поэтому оно должно действительно идти по собственному try/catch. Однако это общий код, который будет происходить часто, поэтому Do not Repeat Yourself и поместите закрытие в статический метод (как предполагает Ник Холт) таким образом, у вас не будет двух элементов try/catch в том же методе, делая код более легким для чтения и наблюдения.

Ответ 8

В Google Guava есть удобный метод Closeables # closeQuitely - он может использоваться для любого Closeable

Ответ 9

Можем ли мы попробовать блок, за которым следует, наконец, bock и блок catch позже?

Ответ 10

просто запомните.. наконец-то всегда выполняйте выполнение либо с помощью try, либо catch.