Java 7 Автоматическое управление ресурсами JDBC (приложение try-with-resources)
Как интегрировать общую идиому JDBC для создания/получения соединения, запрашивая базу данных и, возможно, обрабатывая результаты с помощью автоматического управления ресурсами Java 7, оператор try-with-resources? (Tutorial)
Перед Java 7 обычный шаблон был примерно таким:
Connection con = null;
PreparedStatement prep = null;
try{
con = getConnection();
prep = prep.prepareStatement("Update ...");
...
con.commit();
}
catch (SQLException e){
con.rollback();
throw e;
}
finally{
if (prep != null)
prep.close();
if (con != null)
con.close();
}
С Java 7 вы можете использовать:
try(Connection con = getConnection(); PreparedStatement prep = con.prepareConnection("Update ..."){
...
con.commit();
}
Это закроет Connection
и PreparedStatement
, но как насчет откат? Я не могу добавить предложение catch, содержащее откат, потому что соединение доступно только в блоке try.
Вы все еще определяете соединение вне блока try? Какова наилучшая практика здесь, особенно если используется объединение пулов?
Ответы
Ответ 1
try(Connection con = getConnection()) {
try (PreparedStatement prep = con.prepareConnection("Update ...")) {
//prep.doSomething();
//...
//etc
con.commit();
} catch (SQLException e) {
//any other actions necessary on failure
con.rollback();
//consider a re-throw, throwing a wrapping exception, etc
}
}
В соответствии с документацией oracle вы можете объединить блок try-with-resources с обычным блоком try. IMO, приведенный выше пример фиксирует правильную логику, которая:
- Попытайтесь закрыть PreparedStatement, если ничего не получится.
- Если во внутреннем блоке что-то пойдет не так, (независимо от того, что есть) откат текущей транзакции
- Попытка закрыть соединение независимо от того, что
- Если что-то пойдет не так, закрыв соединение, вы не сможете отменить транзакцию (как тот метод в соединении, который сейчас находится в неопределенном состоянии), поэтому не пытайтесь
В java 6 и ранее я сделал бы это с тройным вложенным набором блоков try (внешний try-finally, middle try-catch, inner try-finally). Синтаксис ARM делает этот терьер.
Ответ 2
IMO, объявив, что Connection и PreparedStatement вне try-catch - лучший способ, доступный в этом случае.
Ответ 3
Если вы хотите использовать объединенное соединение в транзакции, вы должны использовать его следующим образом:
try (Connection conn = source.getConnection()) {
conn.setAutoCommit(false);
SQLException savedException = null;
try {
// Do things with connection in transaction here...
conn.commit();
} catch (SQLException ex) {
savedException = ex;
conn.rollback();
} finally {
conn.setAutoCommit(true);
if(savedException != null) {
throw savedException;
}
}
} catch (SQLException ex1) {
throw new DataManagerException(ex1);
}
Этот пример кода обрабатывает значения автосохранения.