Требуется откат, если java.sql.Connection # commit() выдает исключение?
Согласно документация JAVA, Connection#commit()
может бросить SQLException
. Мой вопрос заключается в том, следует ли еще откатить откат в этом сценарии.
Например:
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
con.commit();
} catch (SQLException e) {
if (con != null) {
// what if con.commit() failed, is this still necessary,
// will it hurt anything?
con.rollback();
}
} finally {
if (con != null) {
con.close();
}
}
Я фактически завернул вызов con.rollback() в другой метод, который игнорирует любые исключения, которые он выбрал, поэтому я думаю, что я в порядке. Я просто задавался вопросом, был ли это лучший способ справиться с ситуацией.
Ответы
Ответ 1
Я бы сделал явный откат только для целей очистки. Хотя изменения не будут сохраняться в db в любом случае, кажется, что явным образом позволяю базе данных знать, что вы здесь сделали. Точно так же, как вы закрываете соединение явно, не дожидаясь, когда объект Connection будет собран с помощью мусора.
Это, очевидно, не технический ответ, и мне также было бы интересно узнать, есть ли практический момент в этом.
Ответ 2
Откат важен, даже если commit завершился неудачно, согласно Java 1.6 JDBC docs:
Настоятельно рекомендуется, чтобы приложение явно фиксировало или возвращает активную транзакцию до вызова метода close. Если вызывается метод close, и есть активная транзакция, результаты определяются по реализации.
Это означает, что если вы явно не вызываете откат, некоторые реализации JDBC могут вызывать фиксацию перед закрытием соединения.
Еще одна веская причина отката - это предложение Xepoch, и при использовании пула соединений это еще более важно.
Когда вы получаете соединение из пула соединений, большинство реализаций выполнит connection.setAutoCommit(defaultAutoCommit)
перед тем, как дать вам соединение и в соответствии с JavaDocs:
Если этот метод вызывается во время транзакции и режима автоматической фиксации, транзакция совершена
Если connection.rollback()
выдает исключение - тогда это сложно...
Ответ 3
"Возвращает открытое соединение?" Если это соединение используется в пуле (и может быть в будущем), вы не хотите, чтобы другая транзакция выполняла вашу более раннюю работу. Я видел МНОГО случаев клиента/решения о подключении пула подключенных драйверов, которые соответствуют интерфейсам JDBC, и Connection.close()
также можно использовать, чтобы просто вернуть соединение обратно в пул.
Кроме того, лучше try{}catch{}
ваш rollback()
(отредактируйте, просто прочитайте весь свой пост, но мне всегда нравится регистрировать исключение при откате)
Ответ 4
Обычно я делаю это:
boolean bSuccess = false;
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
bSuccess = true;
} catch (SQLException e)
{
}
finally
{
try
{
if (con != null)
{
if(bSuccess)
con.commit()
else
con.rollback();
con.close();
}
}
catch(SQLException sqle)
{
log("Log the error here");
// do nothing we tried
}
}
Говоря об этом, я никогда не видел, чтобы комманда или откат не выполнялись, если запросы выполнялись.
Если у вас есть ожидающие транзакции, большинство баз данных имеют инструменты для их освобождения. Большинство серверов приложений будут продолжать повторять транзакции и откаты, пока они не смогут подключиться.
Возможно, вам захочется посмотреть сообщение: Нужно ли писать ROLLBACK, если запросы не выполняются?