我必须在一个函数中修改几个表。他们都必须成功,否则都会失败。如果一个操作失败,我希望它们全部失败。我有以下内容:
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,只是为了简洁而省略。
谢谢
答案 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,您实际上正在做的是允许多个语句一起提交或回滚。否则每个单独的语句将自动提交。