Cuối cùng, tôi đã cố gắng làm cho nó hoạt động nhưng với một số sửa đổi. Ý tưởng là sử dụng LockModeType.PESSIMISTIC_FORCE_INCREMENT thay vì PESSIMISTIC_WRITE. Sử dụng chế độ khóa này, Cron Jobs hoạt động như sau:
- Khi công việc đầu tiên thực hiện lựa chọn cập nhật, mọi thứ diễn ra như mong đợi nhưng phiên bản trên đối tượng thay đổi.
- Nếu một công việc khác cố gắng thực hiện cùng một lựa chọn trong khi công việc đầu tiên vẫn còn trong giao dịch của nó, JPA sẽ khởi chạy OptimisticLockException để nếu bạn bắt gặp ngoại lệ đó, bạn có thể chắc chắn rằng nó đã bị khóa để đọc.
Giải pháp này có các đối tác khác nhau:
- SynchronizedCronJobTask phải có trường phiên bản và được kiểm soát phiên bản với @Version
- Bạn cần xử lý OptimisticLockException và nó phải được bắt bên ngoài phương thức dịch vụ giao dịch để thực hiện khôi phục khi quá trình khóa xảy ra.
- IMHO là một giải pháp không thanh lịch, tệ hơn nhiều so với việc chỉ đơn giản là một chiếc ổ khóa nơi Công việc của Cron đợi các Công việc trước đó hoàn thành.