Nakonec se mi to podařilo, ale s několika úpravami. Cílem je použít LockModeType.PESSIMISTIC_FORCE_INCREMENT namísto PESSIMISTIC_WRITE. Při použití tohoto režimu uzamčení se úlohy Cron chovají následovně:
- Když první úloha provede výběr aktualizace, vše proběhne podle očekávání, ale změní se verze objektu.
- Pokud se jiná úloha pokusí provést stejný výběr, zatímco první je stále v transakci, JPA spustí výjimku OptimisticLockException, takže pokud tuto výjimku zachytíte, můžete si být jisti, že byla vyvolána pro zámek čtení.
Toto řešení má různé protějšky:
- SynchronizedCronJobTask musí mít pole verze a musí být pod kontrolou verzí pomocí @Version
- Musíte zpracovat výjimku OptimisticLockException a měla by být zachycena mimo metodu transakční služby, aby bylo možné provést vrácení zpět, když dojde k odemknutí.
- IMHO je neelegantní řešení, mnohem horší než pouhý zámek, kde Cron Jobs čeká na dokončení předchozích úloh.