Когда нам нужно вызвать java.sql.Connection.rollback ()? - PullRequest
0 голосов
/ 28 марта 2012

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

public void foo() throws Exception {
    Connection conn = null;
    try {
        conn = ...;
        conn.setAutoCommit(false);
        grok(conn);
        conn.commit();
    }
    catch (Exception ex) {
        // do I need to call conn.rollback() here?
    }
    finally {
        if (conn != null) {
            conn.close();
            conn = null;
        }
    }
}

private void grok(Connection conn) throws Exception {
    PreparedStatement stmt = null;
    try {
        // modify table "apple" 
        stmt = conn.prepareStatement(...);
        stmt.executeUpdate();
        stmt.close();

        // modify table "orange"
        stmt = conn.prepareStatement(...);
        stmt.executeUpdate();
        stmt.close();

        ...
    }
    finally {
        if (stmt != null) {
            stmt.close();
        }
    }
}

Мне интересно, нужно ли мне вызывать rollback (), если во время этого процесса что-то идет не так.пул соединений.В приведенном выше примере я также проверяю закрытие каждого PreparedStatement с помощью операторов finally, просто для краткости опущенных.

Спасибо

Ответы [ 3 ]

1 голос
/ 21 мая 2017

Да, вам необходимо вызвать откат, если какое-либо из ваших утверждений не выполнено или вы обнаружили исключение перед вызовом commit.Это старый пост, но принятый ответ неверен.Вы можете попробовать это сами, выдав исключение перед фиксацией и заметив, что ваши вставки все еще попадают в базу данных, если вы не выполняете откат вручную.

Документация JDBC https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html#call_rollback

Пример правильного использования из документа

public void updateCoffeeSales(HashMap<String, Integer> salesForWeek)
    throws SQLException {

    PreparedStatement updateSales = null;
    PreparedStatement updateTotal = null;

    String updateString =
        "update " + dbName + ".COFFEES " +
        "set SALES = ? where COF_NAME = ?";

    String updateStatement =
        "update " + dbName + ".COFFEES " +
        "set TOTAL = TOTAL + ? " +
        "where COF_NAME = ?";

    try {
        con.setAutoCommit(false);
        updateSales = con.prepareStatement(updateString);
        updateTotal = con.prepareStatement(updateStatement);

        for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) {
            updateSales.setInt(1, e.getValue().intValue());
            updateSales.setString(2, e.getKey());
            updateSales.executeUpdate();
            updateTotal.setInt(1, e.getValue().intValue());
            updateTotal.setString(2, e.getKey());
            updateTotal.executeUpdate();
            con.commit();
        }
    } catch (SQLException e ) {
        JDBCTutorialUtilities.printSQLException(e);
        if (con != null) {
            try {
                System.err.print("Transaction is being rolled back");
                con.rollback();
            } catch(SQLException excep) {
                JDBCTutorialUtilities.printSQLException(excep);
            }
        }
    } finally {
        if (updateSales != null) {
            updateSales.close();
        }
        if (updateTotal != null) {
            updateTotal.close();
        }
        con.setAutoCommit(true);
    }
}
1 голос
/ 28 марта 2012

Вам не нужно звонить rollback().Если соединение закрывается без завершения commit(), оно будет откатано.

Вам также не нужно устанавливать conn на null;и поскольку блок try начинается после инициализации conn (при условии, что ... не может вычислить нулевое значение), вам также не нужен != null in finally.

0 голосов
/ 28 марта 2012

Если вы вызываете «commit», транзакция будет зафиксирована. Если у вас есть несколько операторов вставки / обновления, и одна из них не выполнена, фиксация приведет к вставкам / обновлениям, которые не удалось зафиксировать в базе данных. Так что да, если вы не хотите, чтобы другие операторы фиксировали в БД, вам нужно вызвать откат. По сути, вы устанавливаете false в autocommit, позволяя фиксировать или откатывать несколько операторов вместе. В противном случае каждое отдельное утверждение будет автоматически зафиксировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...