Перехватить транзакцию только тогда, когда она обязательно будет совершена, но до совершения
Контекст - это Java - JPA с Hibernate и Spring.
Возьмем сценарий двухфазного протокола фиксации (но только с одним ресурсом):
3,1. Если да из базы данных
3.1.1. (Сделать обратный вызов в коде) - не является частью протокола
3.1.2. Commit to database
3.2 Если no
3.2.1 Откат к базе данных
То, что я хочу, - это способ сделать обратный вызов из 3.1.1 в коде, но только тогда, когда известно, что транзакция будет совершена, но до того, как это действительно произойдет. Кроме того, если здесь вызывается исключение, транзакция должна быть отменена.
Используя TransactionSynchronization
(*) из Spring, вы можете перехватить транзакцию до ее совершения/завершения или после ее совершения/завершения.
-
beforeCommit()
обратный вызов говорит, что откат может все еще возникать после вызова метода;
-
beforeComplete()
вызывается, даже если транзакция терпит неудачу.
-
afterCommit/Complete()
вызывается после того, как транзакция фактически была привязана к базе данных, и нет возможности отката.
Теперь, когда я выгляжу, кажется, что я хочу другой в полном двухфазном протоколе фиксации; но мне интересно, есть ли обходной путь в Spring. Разница в том, что вызов, выполняемый в обратном вызове, нельзя отменить.
(*) из Spring 4.2 очень прост с @TransactionalEventListener
и TransactionPhase
, который прекрасно абстрагирует TransactionSynchronization
Ответы
Ответ 1
Я просто хочу сначала вернуться к транзакции, будучи частью работы, которая либо проходит, либо все терпит неудачу. С тем, что вы говорите о своем методе, о том, что он не может быть откат и должен выполняться между началом и концом транзакции, тогда мне жаль, что у вас нет транзакции.
Вы можете сделать много проверок в своем методе, чтобы убедиться, что вероятный откат отката чрезвычайно тонкий, но всегда будет шанс, что ваш метод будет выполнен и произойдет откат, но этот шанс может быть крайне незначительным и вы можете быть довольны этим, я не знаю.
Edit:
Я думаю, что аналогия была бы приятной.
Случай 1:
Таким образом, классический пример сделки заключается в покупке банана в магазине, если у вас нет денег, или в магазине нет банана, в магазине нет денег, вы не получаете банан, это то, что обычно происходит. Но если все условия установлены, транзакция будет успешно выполнена.
Случай 2: Теперь о том, что вы просите. Для аргументов давайте скажем, что вы вор, и вы только хотите украсть банан, если вам это удастся. Вы не можете это знать наверняка, потому что вы спрашиваете о будущем, если вы не гадалка, когда вы идете украсть банан, вас могут поймать.
Если вы вернетесь к первому делу, вы можете проверить, что у вас есть деньги, в магазине есть банан, дайте магазину свои деньги, бросьте всех клиентов, запереть двери в магазин, чтобы магазин был в неизменное состояние. Иди, делай свой метод, который нельзя откат, вернуться в магазин и взять банан. Никто не может заверить вас, что банан все еще будет там, но это очень вероятно.
Ответ 2
В вашем случае один из ваших ресурсов несовместим с двухфазным фиксацией (не с поддержкой XA). Ваша идея идет в направлении шаблона, описанного в параграфе XA и Last Resource Gambit http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html
Использование последнего ресурсного гамбита вкратце объяснено в ответе Как настроить Spring Boot + Bitronix + non-XA Datasource + XA JMS Connection
Кстати, в вашем вопросе не упоминается, какую реализацию управляющего транзакций вы используете (JBossTS, Bitronix JTA, Atomicos Transaction Essentials,...).