Най-накрая успях да го накарам да работи, но с някои модификации. Идеята е да се използва LockModeType.PESSIMISTIC_FORCE_INCREMENT вместо PESSIMISTIC_WRITE. Използвайки този режим на заключване, заданията на Cron се държат по следния начин:
- Когато първото задание направи избора за актуализиране, всичко върви както се очаква, но версията на обекта се променя.
- Ако друго задание се опита да направи същия избор, докато първото е все още в своята транзакция, JPA стартира OptimisticLockException, така че ако хванете това изключение, можете да сте сигурни, че е изхвърлено за заключване на четене.
Това решение има различни колеги:
- SynchronizedCronJobTask трябва да има поле за версия и да е под контрол на версиите с @Version
- Трябва да обработвате OptimisticLockException и то трябва да бъде уловено извън метода на транзакционната услуга, за да извършите връщане назад, когато се случи деблокирането.
- IMHO е неелегантно решение, много по-лошо от просто заключване, при което Cron Jobs чакат предишните задачи да завършат.