Попробуйте-поймать-наконец, а затем снова попробовать поймать

Я часто сталкивался с такими ситуациями, как:

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

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

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

 Tom Hawtin - tackline26 авг. 2009 г., 18:34
Вы, вероятно, обнаружите, что получение ресурсов также дает результат. (Так что действительно используйте Сет 'ответ.)

Ответы на вопрос(9)

а затем, наконец, bock и потом перехватить блок?

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

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

вы неЯ не хочу делать что-то большее, чем записать исключение, которое происходит при закрытии ресурса, поэтому он действительно должен идти своим собственным try / catch. Тем не менее, это общий код, который будет происходить часто, так чтоПовторите Себя и поместите закрытие в статическом методе (как предлагает Ник Холт) так, как вы выиграли.два элемента try / catch в одном и том же методе упрощают чтение и отслеживание кода.

 supercat17 дек. 2010 г., 04:04
Я не уверен, что согласен с этим. На мой взгляд, сбой при закрытии ресурса представляет собой более серьезную проблему, чем типичное исключение, которое может возникнуть во время использования. Нужно стараться сохранить внутреннее исключение (проще в vb.net, чем в C #), но бросить "более суровый один.
 Yishai21 дек. 2010 г., 14:38
Если вы читаете из сети и все готово, действительно ли это имеет какое-то значение, что ресурс не удалось закрыть? Это конечно неничего не изменить в программе.
 Sam Brinck01 февр. 2012 г., 23:56
если он не оставляет порт открытым и непригодным для использования кем-либо еще

uately - его можно использовать для любого Closeable.

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

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

например

public class IoUtils {

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

}
Решение Вопроса

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);
}
 Ajay27 авг. 2009 г., 06:11
похоже хороший вариант :) спасибо
 Chris Kessel26 авг. 2009 г., 18:57
Это мой выбор и в прошлом, но в наши дни я обнаружил, что есть классы, такие как apache commons DBUtil, которые делают это для вас.

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

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

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

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

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

 Tom Hawtin - tackline26 авг. 2009 г., 18:33
Вы можете, конечно, затем абстрагироваться от этой идиомы.
 Imagist26 авг. 2009 г., 18:07
Тот'технически это не то же самое, но в зависимости от ситуации он может делать то, что хочет Аджай.
 seth26 авг. 2009 г., 18:40
@tackline: спасибо! Hadn»Я видел это раньше. Вот'Ссылка на это для других, кто заинтересован:stackoverflow.com/questions/341971/...
 Yishai26 авг. 2009 г., 18:41
Дело в том, что при таком подходе вы обычно нея не хочу делать то же самое с исключениями, связанными с закрытием, как вы делаете с исключениями в основной части метода - и, что еще хуже, этот код будет проглатывать исключения в основной части, если в конце концов будет выдано исключение.
 seth26 авг. 2009 г., 18:26
@ Имагист: Хорошая мысль. Я'уточню мой ответ. Благодарю.

Ваш ответ на вопрос