Что делать со statment, когда выпадет исключение при его закрытии в Java?
Знакомые рассказывали, что на приемке проекта у них в команде проверяющий указывал им на явное закрытие объекта Statement. Я тоже задался таким вопросом и пошёл смотреть, что по этому поводу говорит официальная документация:
It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.
Следовательно, хорошей практикой является явное закрытие Statement, делается это, судя по всем, таким образом:
try {
// работа со statemen'ом
} catch (SQLException e) {
LOGGER.error("Failed to execute SQL statement: {}.", SQL_PROCEDURE_CREATE_ACCOUNT);
throw new DaoException("Failed to execute SQL statement: " + SQL_PROCEDURE_CREATE_ACCOUNT, e);
} finally {
try {
statement.close();
} catch (SQLException e) {
//todo а если не удалось закрыть statement, что тогда делать?
LOGGER.error("Database access error occurs when trying to close Statement object.", e);
throw new DaoException("Database access error occurs when trying to close Statement object." + e);
}
}
Вопросы:
- Что делать с объектом
statment, если при попытке его закрытия с помощью явного вызова методаstatement.close()выпадает исключениеSQLException, которое, согласно, официальной документации, может выброситься в следующей ситуации:
Throws: SQLException - if a database access error occurs
- Нужно ли всё таки явно закрывать
statementвызовом методаstatement.close(), если сам объектStatementреализует интерфейсAutoCloseable?
Specified by: close in interface AutoCloseable
Ответы (3 шт):
- Закрывать нужно обязательно. Как и любой объект, который реализует интерфейсы
Closeable/AutoCloseable - Причем лучше всего это делать при помощи оператора try-with-resorces
try (Statement stmt = ....) { // работа со statemen'ом } catch (SQLException e) { LOGGER.error("Failed to execute SQL statement: {}.", SQL_PROCEDURE_CREATE_ACCOUNT); throw new DaoException("Failed to execute SQL statement: " + SQL_PROCEDURE_CREATE_ACCOUNT, e); } - С исключением, которое может возникнуть при закрытии работать как и с любым другим: если можем - обрабатываем, если нет - выпускаем дальше
Вот типичный код для работы с базой данных
try (Connection con = .......) {
......
try (Statement stmt = con.PrepareStatement(...)) {
......
try (ResultSet res = stmt.executeQuery()) {
.........
}
}
}
Сами ответили на свой вопрос
Следовательно, хорошей практикой является явное закрытие
Statement
Правда тут надо добавить, что если выполняется неявное закрытие, т.е. если используется try with resources, то исключение, возникающее при выполнении close() следует отлавливать отдельно.
Интерфейс AutoClosable не закрывает Statement автоматически, а служит для неявного закрытия, как например в ситуации, упомянутой выше.
И теперь
//todo а если не удалось закрыть statement, что тогда делать?
Ну тут причины могут быть разные, но в большинстве случаев толку от этого мало, поэтому исключение можно просто игнорировать.
Первый ответ в теме дает более чем исчерпывающий ответ. Если вопрос конкретно в "нужно ли это делать явно или неявно", то тут скорее от проекта зависит. У меня ни разу не требовали явного закрытия. Да и зачем, если есть try-with-resources, который за тебя все закроет и тебе не надо думать об этом. Хотя если же при закрытии требуется организовать какую-то кастомную логику, то лучше использовать явное закрытие т.к. в блоке try можно указать необходимую логику. В общем... Все зависит от ситуации