Когда я очищал какой-то код, FindBugs указывал мне на код JDBC, который использует объекты Connection, CallableStatement и ResultSet. Вот фрагмент из этого кода:
CallableStatement cStmt = getConnection().prepareCall("...");
...
ResultSet rs = cStmt.executeQuery();
while ( rs.next() )
{
...
}
cStmt.close();
rs.close();
con.close();
FindBugs отметил, что они должны быть в конечном блоке. Я начал рефакторинг моего кода, чтобы сделать это, и я начал задаваться вопросом, как обрабатывать код в блоке finally.
Возможно, что создание объектов CallableStatement of Connection вызовет исключение, оставив объект ResultSet равным нулю. Когда я пытаюсь закрыть ResultSet, я получаю исключение NullPointerException, и мое соединение, в свою очередь, никогда не будет закрыто. В самом деле, этот поток раскрывает ту же концепцию и показывает, что упаковка ваших вызовов close() в нулевой проверке является хорошей идеей.
Но как насчет других возможных исключений? Согласно спецификации Java API, Statement.close() может вызывать SQLException "при возникновении ошибки базы данных". Таким образом, даже если мой CallableStatement не является нулевым, и я могу успешно вызвать close() на нем, я все равно могу получить исключение и не иметь возможности закрыть другие ресурсы.
Единственное "безотказное" решение, о котором я могу думать, - это обернуть каждый вызов 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 */ }
}
Мальчик, если это не выглядит ужасно. Есть ли лучший способ сделать это?