Должен ли я ловить исключения, выдаваемые при закрытии java.sql.Connection - PullRequest
14 голосов
/ 29 октября 2008

Connection.close() может выдать SqlException, но я всегда предполагал, что можно игнорировать любые такие исключения (и я никогда не видел код, который не игнорирует их).

Обычно я бы написал:

 try{
    connection.close();
 }catch(Exception e) {}

или

 try{
    connection.close();
 }catch(Exception e) {
     logger.log(e.getMessage(), e); 
 }

Вопрос:

  1. Это плохая практика (и у кого-нибудь были проблемы при игнорировании таких исключений).
  2. Когда Connection.close() выдает любое исключение.
  3. Если это плохо, как я должен обработать исключение.

Комментарий:

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

Кто-нибудь знает, когда Connection.close() может что-нибудь бросить?

Ответы [ 12 ]

13 голосов
/ 30 октября 2008

На самом деле то, что вы делаете, - это (почти) лучшая практика :-) вот что я увидел в Spring JdbcUtils.java. Итак, вы можете добавить другой блок Catch.

/**
 * Close the given  ResultSet and ignore any thrown exception.
 * This is useful for typical finally blocks in manual  code.
 * @param resultSet the  ResultSet to close
 * @see javax.resource.cci.ResultSet#close()
 */
private void closeResultSet(ResultSet resultSet) {
  if (resultSet != null) {
    try {
      resultSet.close();
    }
    catch (SQLException ex) {
      logger.debug("Could not close  ResultSet", ex);
    }
    catch (Throwable ex) {
      // We don't trust the  driver: It might throw RuntimeException or Error.
      logger.debug("Unexpected exception on closing  ResultSet", ex);
    }
  }
}
12 голосов
/ 29 октября 2008

В общем, у меня были дни, потраченные впустую людьми, выбрасывающими подобные исключения.

Я рекомендую придерживаться нескольких основных правил с исключениями:

Если вы абсолютно уверены, что вы НИКОГДА не вызовете проблему с проверенным исключением, поймайте ПРОСТО это исключение и прокомментируйте, почему вам не нужно его обрабатывать. (Sleep создает исключение InterruptedException, которое всегда можно игнорировать, если вы на самом деле не заинтересованы в нем, но, честно говоря, это единственный случай, который я обычно игнорирую - даже при этом, если вы его никогда не получаете, какова стоимость его регистрации?)

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

Если вы не видите, как может быть выбрано проверенное исключение, перехватите его и перебросьте как неконтролируемое исключение.

Если вы точно знаете, что является причиной исключения, поймайте его и запишите точно, почему, в этом случае вам на самом деле не нужна трассировка стека, если вы очень четко знаете, что ее вызывает (и вы могли бы упомянуть класс, который войдите в систему, если вы еще не используете log4j или что-то еще.

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

Обновление: Основная проблема здесь в том, что проверенные исключения являются плохими. Единственный широко используемый язык, на котором они существуют, - это Java. Теоретически они аккуратны, но в действии они вызывают такое поведение, что вы не можете получить с непроверенными исключениями.

Многие люди прокомментировали тот факт, что я сказал, что скрывать их иногда хорошо. Чтобы быть конкретным, я могу вспомнить один случай:

try {
    Thread.sleep(1000);
catch (InterruptedException e) {
    // I really don't care if this sleep is interrupted!
}

Я полагаю, что основная причина, по которой я считаю, что это использование нормально, заключается в том, что такое использование InterruptedException, во-первых, является злоупотреблением проверенным шаблоном исключения, оно скорее сообщает о результате сна, чем указывает на условие исключения.

Было бы гораздо разумнее иметь:

boolean interrupted=Thread.sleep(1000);

Но они очень гордились своим новым шаблоном проверенных исключений, когда они впервые создали Java (понятно, что это действительно изящная концепция - только на практике не получается)

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

6 голосов
/ 30 октября 2008

Как минимум, всегда всегда всегда регистрировать исключения, которые вы ловите и не действуете.

Молчаливые исключения, которые проглатываются без малейшего взгляда, являются худшими.

3 голосов
/ 29 октября 2008

Мне лично нравится ваша вторая идея, по крайней мере, регистрировать ошибку. Поскольку вы ловите исключение, теоретически возможно поймать что-то, кроме исключения SQL. Я не уверен, что может случиться или как редко (например, из-за нехватки памяти и т. Д.), Но подавление всех ошибок мне не кажется правильным.

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

Гипотетическая ситуация: что если бы в вашем sql была открытая транзакция, и закрытие соединения вызвало исключение из-за этого, вы хотели бы подавить эту ошибку? Даже подавление исключений SQLE может быть немного опасным.

1 голос
/ 09 марта 2009

Обратите внимание, что Apache Commons DButils предоставляет метод closeQuietly(), который можно использовать, чтобы избежать загромождения вашего кода «избыточными» перехватами. Заметьте, я не защищаю глотание исключений, но для этого close() сценария я думаю, что это в целом приемлемо.

1 голос
/ 30 октября 2008

Вы также можете выдать исключение RuntimeException:

try {
    connection.close();
 } catch(Exception e) {
     throw new RuntimeException(e); 
 }

Вам не придется изменять сигнатуру метода, и вы сможете позже использовать метод Exception.getCause, чтобы найти причину проблемы.

1 голос
/ 30 октября 2008

В идеальном мире вы никогда не должны делать ничего с исключением, конечно, в идеальном мире вы никогда не получите исключения 8 -)

Итак, вы должны изучить влияние различных вариантов.

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

Пустой обработчик: все операции с базой данных завершены, ничего не осталось, кроме как очистить ресурсы. Если в этот момент возникает исключение, оно, скорее всего, не влияет на выполненную работу, поэтому метод успешно завершается. Следующий доступ к базе данных может столкнуться с той же проблемой, но это должно произойти в начале транзакции, где он по ошибке завершится ошибкой, а затем будет обработан соответствующим образом. Если проблема решится сама собой, то не будет никаких признаков того, что что-то пошло не так.

Это довольно типичный сценарий размещения операций close () в блоке finally, чтобы гарантировать выполнение очистки, поскольку мы не хотим, чтобы другие сбои препятствовали очистке ресурса. Если ошибки не произошло, ваш метод не должен завершиться ошибкой, когда его работа успешно завершена. В этом случае обработка пустых исключений вполне нормальная.

Конечно, мнения будут разными.

1 голос
/ 29 октября 2008

Вы должны обработать исключение. Это не плохая практика. Представьте, что вы потеряли сеть непосредственно перед закрытием соединения dabatase. Это, вероятно, вызовет исключение.

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

Вам также следует подумать о том, возможно ли в этот момент нулевое соединение (это может вызвать исключение NullPointerException) или нет.

if (connection != null) {
   try { 
      connection.close(); 
   } catch (SQLException sqle) { 
      logger.log(e.getMessage(), e); 
   }
}
0 голосов
/ 22 сентября 2012

Рекомендуется обрабатывать исключение во время закрытия соединения с базой данных. Потому что в какой-то момент времени в вашем коде, если вы пытаетесь получить доступ к объектам оператора или набора результатов, это автоматически вызовет исключение. Так что лучше обработать исключение.

0 голосов
/ 04 апреля 2010

Если вы можете справиться с этим, то сделайте это (и запишите, если это было неожиданно). Если вы не можете справиться с этим, то сбросьте его правильно, чтобы код, описанный выше, мог его обработать.

При тихом проглатывании исключений человек не может исправить информацию, необходимую для исправления кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...