Нужен ли откат, если java.sql.Connection # commit () выдает исключение? - PullRequest
17 голосов
/ 25 сентября 2010

Согласно документации 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 () в другой метод, который игнорирует любые исключения, вызванные им, поэтому я думаю, что я в порядке. Мне просто интересно, если это лучший способ справиться с вещами.

Ответы [ 4 ]

18 голосов
/ 10 марта 2012

Откат важен даже в случае неудачной фиксации, в соответствии с Java 1.6 JDBC документами :

Настоятельно рекомендуется, чтобы приложение явно зафиксировало или откатило активную транзакцию додля вызова метода close.Если вызывается метод close и существует активная транзакция, результаты определяются реализацией.

Это означает, что если вы явно не вызываете откат, некоторая реализация JDBC может вызвать commit перед закрытием соединения.

Еще одна веская причина для отката - это, как предложил Xepoch, и при использовании пула соединений это еще более важно.При получении соединения из пула соединений большинство реализаций выполнят connection.setAutoCommit(defaultAutoCommit) перед тем, как дать вам соединение, и в соответствии с JavaDocs:

Если этот метод вызывается во время транзакции и режима автоматической фиксацииизменяется, транзакция совершается

Если connection.rollback() выдает исключение - тогда это сложная задача ...

6 голосов
/ 25 сентября 2010

Я бы сделал явный откат только для целей очистки.Хотя изменения не будут сохранены в БД, в любом случае, неплохо бы явно сообщить базе данных, что вы здесь закончили.Точно так же, как вы явно закрываете соединение, не дожидаясь, пока объект Connection будет собирать мусор.

Это, очевидно, не технический ответ, и мне также было бы интересно узнать, есть ли практический смысл в выполнениипоэтому.

4 голосов
/ 25 сентября 2010

"Возвращает открытое соединение?"Если это соединение является общим в пуле (и может быть в будущем), вам не нужна другая транзакция, совершающая вашу предыдущую работу.Я видел МНОГИЕ клиенты / решения случаев подключения драйвера пула соединений, которые соответствуют интерфейсам JDBC, и Connection.close() также можно использовать для простого возврата соединения обратно в пул.

Также лучше try{}catch{}ваш rollback() (отредактируйте, просто прочитайте весь пост, но мне всегда нравится регистрировать исключение при откате)

1 голос
/ 25 сентября 2010

Обычный способ сделать это:

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, если запросы не выполняются?

...