Где закрыть java PreparedStatements и ResultSets?

В VS2015 можно «игнорировать пустое пространство» при сравнении нажатия маленькой иконки с символом =. Перейдите в раздел «Просмотр / Панели инструментов / Сравнить файлы». На панели инструментов нажмите «Игнорировать триггерные пробелы».

35
задан Tom Hawtin - tackline 26 November 2008 в 20:02
поделиться

8 ответов

Для файлового ввода-вывода я обычно добавляю попытку/выгоду к наконец блок. Однако необходимо бояться выдавать любые исключения от наконец блок, так как они заставят исходное исключение (если таковые имеются) быть потерянным.

См. эта статья для более определенного примера закрытия соединения с базой данных.

9
ответ дан Michael Myers 10 October 2019 в 11:36
поделиться

В Java 7 Вы не должны закрывать их явно, но использование автоматическое управление ресурсами , чтобы гарантировать, что ресурсы закрываются, и исключения обработаны соответственно. Обработка исключений работает как это:

Exception in try | Exception in close | Result
-----------------+--------------------+----------------------------------------
      No         |        No          | Continue normally
      No         |        Yes         | Throw the close() exception
      Yes        |        No          | Throw the exception from try block
      Yes        |        Yes         | Add close() exception to main exception
                 |                    |  as "suppressed", throw main exception

, Надо надеяться, который имеет смысл. В позволяет симпатичный код, как это:

private void doEverythingInOneSillyMethod(String key)
  throws MyAppException
{
  try (Connection db = ds.getConnection()) {
    db.setReadOnly(true);
    ...
    try (PreparedStatement ps = db.prepareStatement(...)) {
      ps.setString(1, key);
      ...
      try (ResultSet rs = ps.executeQuery()) {
        ...
      }
    }
  } catch (SQLException ex) {
    throw new MyAppException("Query failed.", ex);
  }
}
<час>

До Java 7, лучше использовать вложенный наконец блоки, вместо того, чтобы тестировать ссылки на пустой указатель.

пример, который я покажу, мог бы выглядеть ужасным с глубоким вложением, но на практике, хорошо разработанный код, вероятно, не собирается создавать соединение, оператор и результаты все в том же методе; часто, каждый уровень вложения включает передачу ресурса к другому методу, который использует его в качестве фабрики для другого ресурса. С этим подходом исключения из close() замаскируют исключение изнутри try блок. Это может быть преодолено, но это приводит к еще более грязному коду и требует пользовательского класса исключений, который обеспечивает "подавленное" объединение в цепочку исключения, существующее в Java 7.

Connection db = ds.getConnection();
try {
  PreparedStatement ps = ...;
  try {
    ResultSet rs = ...
    try {
      ...
    }
    finally {
      rs.close();
    }
  } 
  finally {
    ps.close();
  }
} 
finally {
  db.close();
}
45
ответ дан erickson 10 October 2019 в 11:36
поделиться

Не тратьте впустую свое время, кодируя управление исключением низкого уровня, используйте высокоуровневый API как Spring-JDBC или пользовательскую обертку вокруг объектов соединения/оператора/RS, для сокрытия грязной выгоды попытки код, на котором поехали.

7
ответ дан BraveSirFoobar 10 October 2019 в 11:36
поделиться

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

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

Примечание, что Ваше текущее решение не закроет ResultSet при закрытии сбоев PreparedStatement - лучше использовать вложенный наконец блоки.

5
ответ дан Jon Skeet 10 October 2019 в 11:36
поделиться

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

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

public static void close(ResultSet rs, Statement ps, Connection conn)
{
    if (rs!=null)
    {
        try
        {
            rs.close();

        }
        catch(SQLException e)
        {
            logger.error("The result set cannot be closed.", e);
        }
    }
    if (ps != null)
    {
        try
        {
            ps.close();
        } catch (SQLException e)
        {
            logger.error("The statement cannot be closed.", e);
        }
    }
    if (conn != null)
    {
        try
        {
            conn.close();
        } catch (SQLException e)
        {
            logger.error("The data source connection cannot be closed.", e);
        }
    }

}

и затем,

finally {
    close(rs, ps, null); 
}
25
ответ дан Keith Pinson 10 October 2019 в 11:36
поделиться

Сделайте не опускают звонить близко. Это может вызвать проблемы.

я предпочитаю добавлять блок попытки/выгоды к наконец.

0
ответ дан asalamon74 10 October 2019 в 11:36
поделиться

Я использую это..

finally
{
    if (ps != null) ps.close();
    if (rs != null) rs.close();
}
-1
ответ дан Chris Nava 10 October 2019 в 11:36
поделиться

Также примечание:

"Когда объект Оператора закрывается, его текущий объект ResultSet, если Вы существуете, также закрывается".

http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close ()

Должно быть достаточно окружить только PreparedStatement наконец, и только если это уже не закрывается. Если Вы захотите быть действительно конкретными, хотя, закройте ResultSet СНАЧАЛА, не после закрытия PreparedStatement (закрывающийся, это после, как некоторые примеры здесь, должно на самом деле гарантировать исключение, так как это уже закрывается).

7
ответ дан 27 November 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: