Как правильно закрыть ресурсы

Пока я очищал некоторый код, FindBugs указал мне на фрагмент кода JDBC, который использует объекты Connection, CallableStatement и ResultSet. Вот фрагмент этого кода:

CallableStatement cStmt = getConnection().prepareCall("...");
...
ResultSet rs = cStmt.executeQuery();

while ( rs.next() )
{
    ...
}

cStmt.close();
rs.close();
con.close();

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

Возможно, создание CallableStatement объектов Connection вызовет исключение, в результате чего мой объект ResultSet останется нулевым. Когда я пытаюсь закрыть ResultSet, Я получу исключение NullPointerException, и мое соединение, в свою очередь, никогда не закроется. В самом деле, этот поток поднимает ту же концепцию и показывает, что упаковка ваших вызовов close () в нулевую проверку - хорошая идея.

Но как насчет других возможных исключений? Согласно спецификации Java API, Statement.close () может генерировать SQLException «при возникновении ошибки базы данных». Таким образом, даже если мой CallableStatement не равен нулю и я могу успешно вызвать для него close (), я все равно могу получить исключение и не иметь возможности закрыть другие мои ресурсы.

Единственное «отказоустойчивое» решение, которое я могу придумать of заключается в том, чтобы заключать каждый вызов close () в отдельный блок try / catch, например:

finally {

    try {
        cStmt.close();
    } catch (Exception e) { /* Intentionally Swallow  Exception */ }

    try {
        rs.close();
    } catch (Exception e) { /* Intentionally Swallow  Exception */ }

    try {
        con.close();
    } catch (Exception e) { /* Intentionally Swallow  Exception */ }

}

Боже, если это не выглядит ужасно. Есть ли лучший способ сделать это?

18
задан Community 23 May 2017 в 12:10
поделиться