Точка сохранения на JDBC
У меня есть код 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
работа была выполнена правильно?
2 ответа
Будет рассматривать это как несколько транзакций. Следовательно, вы можете справиться с этим с помощью нескольких блоков 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();
}
}
Тогда вы можете иметь различные методы, которые могут быть вызваны независимо или в комбинации. В приведенном ниже примере 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 {
}
}
}
Таким образом, если что-то пойдет не так, он полностью откатывается (в результате обработки исключений), но он фиксирует только всю транзакцию, а не частично завершенную транзакцию.