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