Какова наилучшая практика реализации перезапуска транзакции при возникновении взаимоблокировки или тайм-аута блокировки при использовании Spring (в частности, рекомендуемый подход Spring: декларативные транзакции)?
Спасибо,
Асаф
Какова наилучшая практика реализации перезапуска транзакции при возникновении взаимоблокировки или тайм-аута блокировки при использовании Spring (в частности, рекомендуемый подход Spring: декларативные транзакции)?
Спасибо,
Асаф
Я чувствую, что у Spring должен быть хороший ответ на этот вопрос (по крайней мере, в виде документации или какого-то перехватчика повторных попыток). Увы, это не так.
Вероятно, лучший способ справиться с повторными попытками (если вы хотите продолжать быть «декларативным» в отношении вещей) — это написать собственную реализацию перехватчика, которая будет автоматически повторять транзакцию заданное количество раз. Для начала изучите Spring TransactionInterceptor
, который управляет поведением start/rollback/commit для декларативных транзакций. Если вы используете Hibernate, обратите внимание, как он обрабатывает привязку/отвязку сеанса Hibernate к текущему потоку.
На что следует обратить внимание, если вы используете Hibernate:
session.clear()
недостаточно.)MethodInterceptor.invoke()
-- экземпляр MethodInvocation
, который передается в this, может иметь состояние; вам может потребоваться клонировать его перед использованием в перехватчике.Я рекомендую использовать класс org.springframework.retry.interceptor.RetryOperationsInterceptor
из весеннего повтора проекта, сконфигурированный как это:
<aop:config>
<aop:pointcut id="transactional" expression="execution(* com...*Service.remoteCall(..))" />
<aop:advisor pointcut-ref="transactional" advice-ref="retryAdvice" order="-1"/>
</aop:config>
<bean id="retryAdvice" class="org.springframework.retry.interceptor.RetryOperationsInterceptor"/>
Но если вы все же хотите реализовать его самостоятельно, пример АОП из документации Spring — хорошее начало.
Универсального ответа нет, поскольку он зависит от специфики приложения. Например, вы можете захотеть выполнить автоматический перезапуск транзакционной операции или уведомить пользователя о сбое операции и запросить явное подтверждение повторной попытки и т. д.
Я бы использовал АОП в случае сценария автоматического перезапуска.
У меня был тот же вопрос несколько лет назад, и в итоге я написал мое собственное решение как аспект АОП, который в конечном итоге выглядит в вашем коде следующим образом:
@RetryTransaction
@Transactional
public void doSomething() {
....
}