我们什么时候需要调用java.sql.Connection.rollback()?

时间:2012-03-28 05:07:48

标签: java jdbc

我必须在一个函数中修改几个表。他们都必须成功,否则都会失败。如果一个操作失败,我希望它们全部失败。我有以下内容:

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()。

其他信息:我正在使用连接池。在上面的示例中,我还确保使用finally语句关闭每个PreparedStatement,只是为了简洁而省略。

谢谢

3 个答案:

答案 0 :(得分:1)

您无需致电rollback()。如果连接在没有完成commit()的情况下关闭,它将被回滚。

您也不需要将conn设置为null;并且由于try块在conn初始化后开始(假设...无法求值为null),您也不需要!= null中的finally。< / p>

答案 1 :(得分:1)

是的,如果您的任何语句失败或者在调用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);
    }
}

答案 2 :(得分:0)

如果您调用“commit”,则将提交事务。如果您有多个插入/更新语句,并且其中一个语句失败,则提交将导致无法提交到数据库的插入/更新。所以,是的,如果您不希望其他语句提交到db,则需要调用rollback。通过将autocommit设置为false,您实际上正在做的是允许多个语句一起提交或回滚。否则每个单独的语句将自动提交。