В JDBC, когда autocommit имеет значение false и явные точки сохранения не установлены, это хороший стиль или пустая трата для отката? - PullRequest
36 голосов
/ 01 июля 2010

Скажем, у вас есть следующий код:

Connection conn;
try
{
   conn = ... // get connection
   conn.setAutoCommit(false);

   ... // Do some modification queries and logic

   conn.commit()
} catch(SQLException e)
{
    conn.rollback() // Do we need this?
    conn.close()
}

В этом коде, если есть исключение, лучше ли просто закрыть соединение (поскольку автокоммит отключен) или явно откатить и затем закрыть соединение? Нет очков сохранения.

Мне кажется, что имеет смысл добавить вызов отката, потому что:

1) Кто-то в будущем может добавить очки сохранения, но забудет добавить откат

2) Улучшает читабельность

3) Это ничего не должно стоить, верно?

Но, очевидно, ни один из них не является особенно убедительным. Любая стандартная практика?

Примечание: я знаю о необходимости повторной попытки / уловки при закрытии и откате. На самом деле у меня есть промежуточное ПО, которое абстрагирует доступ к базе данных и позаботится об этом, но мне было интересно, было ли добавление этого излишним.

Ответы [ 2 ]

46 голосов
/ 02 июля 2010

Обычная идиома следующая:

public void executeSomeQuery() throws SQLException {
    try (Connection connection = dataSource.getConnection()) {
        connection.setAutoCommit(false);

        try (PreparedStatement statement = connection.prepareStatement(SOME_SQL)) {
            // Fire transactional queries here.

            connection.commit();
        } catch (SQLException e) {
            connection.rollback();
            throw e;
        }
    }
}

Обратите внимание, что оператор try-with-resources в Java 7 всегда неявно вызывает close() ресурса, когда заканчивается блок try, как если бы это происходило в finally.

Вызов rollback() также обязателен, когда речь идет о соединении в пуле . А именно, он сбросит транзакционное состояние соединения. close() соединения в пуле этого не сделает, это будут делать только commit() и rollback(). Отказ от вызова rollback() может привести к тому, что при следующей аренде пулированного соединения в его памяти останутся (успешные) запросы предыдущей транзакции.

См. Также Javadoc Connection#close() (ударение не мое):

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

2 голосов
/ 02 июля 2010

Закрытие должно откатиться, потому что оно не будет зафиксировано, когда ресурсы будут освобождены, но хорошо, чтобы обработка ошибок была конкретной, поэтому, если вы хотите откатить исключение, сделайте это.Затем вы можете выполнить очистку в блоке finally {}.Откат () происходит только при ошибке, в этом случае ваш коммит () не выполнен или даже не был достигнут.

Connection conn = null;
try {
    conn = ...

    ...
    conn.commit();
}
catch (SQLException e) {
    if (conn != null) {
        conn.rollback();
    }
}
finally {
    if (conn != null) {
        conn.close();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...