我有一个JDBC代码,其中存在多个Savepoints
;像这样的东西:
1st insert statement
2nd insert statement
savepoint = conn.setSavepoint("S1");
1st insert statement
2nd update statement
savepoint = conn.setSavepoint("S2");
1st delete statement
2nd delete statement
savepoint = conn.setSavepoint("S3");
1st insert statement
2nd delete statement
savepoint = conn.setSavepoint("S4");
现在在catch块中,我正在捕获异常并检查Savepoint
是否为null
;如果是,则回滚整个连接,否则回滚到Savepoint
。但是我无法理解直到哪个Savepoint
会回滚。
如果我将所有保存点名称更改为" S1"是否可以。 ?在那种情况下,我将如何理解Savepoint
在Savepoint
之前正常工作的次数?
请在正确执行{{1}}工作之前告知如何理解?
答案 0 :(得分:3)
在这种情况下,我发现棘手的部分是确保仅在所有插入成功时提交事务,但如果任何插入失败则回滚所有更新。我使用了一个保存点堆栈来处理这种情况。高度简化的代码如下:
连接包装类:
public class MyConnection {
Connection conn;
static DataSource ds;
Stack<Savepoint> savePoints = null;
static {
//... stuff to initialize datasource.
}
public MyConnection() {
conn = ds.getConnection();
}
public void beginTransaction() {
if (savePoints == null) {
savePoints = new Stack<Savepoint>();
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
} else {
savePoints.push(conn.setSavepoint());
}
}
public void commit() throws SQLException {
if (savePoints == null || savePoints.empty()) {
conn.commit();
} else {
Savepoint sp = savePoints.pop();
conn.releaseSavepoint(sp);
}
}
public void rollback() throws SQLException {
if (savePoints == null || savePoints.empty()) {
conn.rollback();
} else {
Savepoint sp = savePoints.pop();
conn.rollback(sp);
}
}
public void releaseConnection() {
conn.close();
}
}
然后,您可以拥有可以单独或组合调用的各种方法。在下面的示例中,methodA可以单独调用,也可以调用methodB。
public class AccessDb {
public void methodA(MyConnection myConn) throws Exception {
myConn.beginTransaction();
try {
// update table A
// update table B
myConn.commit();
} catch (Exception e) {
myConn.rollback();
throw e;
} finally {
}
}
public void methodB(MyConnection myConn) throws Exception {
myConn.beginTransaction();
try {
methodA(myConn);
// update table C
myConn.commit();
} catch (Exception e) {
myConn.rollback();
throw e;
} finally {
}
}
}
这样,如果出现任何问题,它会完全回滚(作为异常处理的结果),但它只提交整个事务而不是提交部分完成的事务。
答案 1 :(得分:2)
将此视为多个交易。因此,您可以使用多个try / catch块来处理此问题。您似乎也在覆盖保存点对象,因此回滚是不可行的。
更多信息。 JDBC还支持设置保存点,然后回滚到指定的保存点。以下方法可用于定义保存点。
SavePoint savePoint1 = connection.setSavePoint();
使用带参数的回滚调用将事务回滚到已定义的保存点。
connection.rollback(savePoint1);
参考。 http://www.sourcetricks.com/2014/08/jdbc-handling-transactions.html