У меня есть 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
работа была выполнена правильно?
Будет рассматривать это как несколько транзакций. Следовательно, вы можете справиться с этим несколькими блоками try/catch. Вы также, кажется, переписываете объекты точки сохранения, поэтому было бы невозможно откат.
Больше информации. JDBC также поддерживает установку точек сохранения, а затем откат в указанную точку сохранения. Для определения точек сохранения можно использовать следующий метод.
SavePoint savePoint1 = connection.setSavePoint();
Откат транзакции в уже определенную точку сохранения с помощью обратного вызова с аргументом.
connection.rollback(savePoint1);
Справка. http://www.sourcetricks.com/2014/08/jdbc-handling-transactions.html
В таких случаях я обнаружил, что сложная часть заключается в том, чтобы убедиться, что вы совершили транзакцию, только если все вставки успешно, но откатите все обновления, если какая-либо вставка завершилась с ошибкой. Я использовал стек точки сохранения для обработки таких ситуаций. Очень упрощенный код выглядит следующим образом:
Класс оболочки подключения:
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();
}
}
Затем вы можете использовать различные методы, которые могут быть вызваны независимо или в сочетании. В приведенном ниже примере метод А может быть вызван сам по себе или в результате вызова метода Б.
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 {
}
}
}
Таким образом, если что-то пойдет не так, оно полностью откатится (в результате обработки исключений), но только совершит транзакцию, а не совершит частично завершенную транзакцию.