PROPAGATION_REQUIRED атрибут транзакции весной? - PullRequest
3 голосов
/ 10 августа 2011

В первом примере, приведенном в http://www.vermatech.com/code/SpringTransactionExamples.html,, программа вызывает два метода, например

testModel.deleteAllCountries();
testModel.initializeCountries();

, где initializeCountries выдает исключение времени выполнения.Атрибутом определения транзакции для обоих методов является PROPAGATION_REQUIRED.Тем не менее транзакция по методу deleteAllCountries фиксируется, но транзакция по initializeCountries откатывается (согласно журналам, приведенным в том же примере).

Согласно определению PROPAGATION_REQUIRED, он поддерживает текущую транзакцию;создать новый, если ни один не существует.Поэтому мой вопрос здесь заключается в том, что транзакция в методе initializeCountries должна поддерживать транзакцию в методе deleteAllCountries.Я имею в виду, что оба метода должны рассматриваться как одна транзакция.Насколько я понимаю, полная транзакция должна быть зафиксирована или откатана?Не уверен, почему журналы обрабатывают их отдельно.

1 Ответ

12 голосов
/ 10 августа 2011

«Требуется распространение» определяется как

Поддерживать текущую транзакцию, создать новую, если ее не существует.

В вашем случае выше метод deleteAllCountries выполняется всделка и совершает.При вызове initializeCountries нет текущей транзакции, поэтому она выполняется во второй транзакции, и откат ее не влияет на изменения, сделанные первым методом.

Распространение применяется к вызовам вложенных методов, а не к последующим.Если вы посмотрите на документацию :

Когда для параметра распространения установлено значение PROPAGATION_REQUIRED, для каждого метода, к которому применяется параметр, создается логическая область транзакции.Каждая такая логическая область транзакции может определять состояние только отката отдельно, причем область внешней транзакции логически не зависит от области внутренней транзакции.Конечно, в случае стандартного поведения PROPAGATION_REQUIRED все эти области будут сопоставлены одной и той же физической транзакции.Таким образом, маркер «только откат», установленный во внутренней области транзакции, действительно влияет на вероятность внешней транзакции совершить (как и следовало ожидать).

Однако в случае, когда внутренняя область транзакции устанавливает откатЕдинственный маркер, внешняя транзакция не определилась с самим откатом, и поэтому откат (незаметно вызванный областью внутренней транзакции) является неожиданным.Соответствующее UnexpectedRollbackException выбрасывается в этой точке.Это ожидаемое поведение, так что вызывающий транзакцию никогда не может быть введен в заблуждение, полагая, что фиксация была выполнена, когда она действительно не была выполнена.Таким образом, если внутренняя транзакция (о которой внешний вызывающий не знает) молча помечает транзакцию как только для отката, внешний вызывающий по-прежнему вызывает commit.Внешний вызывающий должен получить исключение UnexpectedRollbackException, чтобы четко указать, что вместо этого был выполнен откат.

тогда вы можете увидеть, что все это касается внутренних и внешних - ни в одном из них не упоминаются последовательные вызовы.В вашем случае вызов deleteAllCountries является самым внешним транзакционным методом, поэтому, когда он успешно завершается, Spring немедленно фиксирует транзакцию.Затем ваш вызов initializeCountries должен быть выполнен в отдельной транзакции, где это самый внешний метод.

Похоже, что Spring будет держать транзакцию открытой после завершения первого метода, но это не так.работает.Чтобы получить желаемый эффект, вы можете создать другой метод в testModel, который обернет вызовы deleteAllCountries и initializeCountries, сделает этот метод транзакционным и присвоит ему атрибут PROPAGATION_REQUIRED.Таким образом, откат второго метода также приведет к откату изменений первого метода, потому что метод обертывания группирует их вместе.В противном случае ничего не говорит Spring, эти вещи должны быть частью одной транзакции.

...