Мне кажется, что у самой Spring должен быть хороший ответ на этот вопрос (по крайней мере, в форме документации или перехватчика повторов). Увы, это не так.
Вероятно, лучший способ обработки повторных попыток (если вы хотите продолжать «декларативно» относиться к вещам) - это написать собственную реализацию перехватчика, которая будет автоматически повторять транзакцию настроенное число раз. Для начала изучите Spring * TransactionInterceptor
, который управляет поведением start / rollback / commit для декларативных транзакций. Если вы используете Hibernate, обратите внимание, как он обрабатывает привязку / отмену привязки сеанса Hibernate к текущему потоку.
На что обращать внимание при использовании Hibernate:
- Ваш «ретранслятор перехвата» должен обязательно отменить привязку любого существующего ранее связанного с потоками сеанса Hibernate и повторно связать новый. Как только исключение (например, взаимоблокировка) генерируется из кода Hibernate / JDBC, соответствующий сеанс Hibernate отравляется и должен быть отброшен. (
session.clear()
недостаточно.)
- Будьте осторожны, если ваши методы транзакционной службы используют объекты сеанса Hibernate в качестве параметров метода. При повторных попытках при сбросе сеанса Hibernate эти объекты будут отсоединены. Вам нужно будет повторно присоединить их, если метод службы предполагает, что они присоединены (например, если они используют лениво загруженные свойства, доступ к которым осуществляется в методе службы, или если вы пытаетесь сохранить их и т. Д.) В общем, лучше, если вы не используйте объекты Hibernate в качестве параметров для методов транзакционного сервиса.
- Вы будете реализовывать
MethodInterceptor.invoke()
- экземпляр MethodInvocation
, который передается этому, может быть с состоянием; вам может понадобиться клонировать его перед использованием в перехватчике.