Как писал @JBNizet, а я читал в других статьях, OptimisticLock решает проблему, потому что она позволяет только одной транзакции, которая изменяет строку, чтобы быть успешной.Другие транзакции выбрасываются с ObjectOptimisticLockingFailureException
.Затем я использовал try{}catch{}
, чтобы сделать рекурсию на ObjectOptimisticLockingFailureException
, чтобы перенаправить обратно к тому же методу
Хитрость заключалась в том, что логика getAndIncreaseCorrectAccountNumber
была в глубоком слое, где в той же транзакции много другихЛогика CRUD
произошла, поэтому мне нужно было потянуть мой try{}catch{}
чуть выше всего верхнего слоя @Transaction
(иначе основной объект был изменен и не был откат, поэтому try{}catch{}
, кажется, работает, когда он находится выше самого верхнего @Transaction
)
В коде, что я сделал:
- В
AccountNumber
добавлена версия строки PostgreSQL для OptimisticLock
@ Column (имя= "version_num") @Version private int version;
В слое хранилища AccountNumberRepository
добавлено @Lock(LockModeType.OPTIMISTIC)
чуть выше метода
Добавлено try{}catch{}
для перехвата OptimisticLock и включения повторения для того же метода
public String submitSomeObjectWithRecursionHandling(@NotNull SomeObject someObject, @NotBlank String accountId){
try {
return submitSomeObject(someObject, accountId);
} catch (ObjectOptimisticLockingFailureException | OptimisticLockException e) {
e.printStackTrace();
return submitSomeObjectWithRecursionHandling(someObject, accountId);
}
}
submitSomeObject(someObject, accountId)
запущено @Transaction
Чего мне не удалось добиться, так это написать интеграционный тест.Итак, я создал 10 из подготовленных к отправке SomeObects
и из Front-End сразу отправил запрос на отправку, и он сначала воспроизвел ошибку с повторной копией accountNumber
, а позже, после исправления, показал, что рекурсия обрабатывает проблему
Если у вас есть несколько способов протестировать это решение в интеграционном тесте, сообщите мне.