javax.persistence.lock.timeout nie działa dla mnie, gdy jest podany jak poniżej
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})
Ale potem spróbowałem czegoś innego, co zadziałało. Zamiast używać @Repository i CrudRepository, teraz konfiguruję hibernację za pomocą menedżera encji. Używany createQuery wraz z blokadą i ustawianiem limitu czasu blokady. I ta konfiguracja działa zgodnie z oczekiwaniami. Mam dwie transakcje działające równolegle i próbuję zablokować dokładnie ten sam wiersz w DB. Pierwsza transakcja jest w stanie uzyskać blokadę WRITE i utrzymuje blokadę przez około 10 sekund przed zwolnieniem blokady. Tymczasem druga transakcja próbuje uzyskać blokadę w tym samym wierszu, ale ponieważ javax.persistence.lock.timeout jest ustawiony na 15 sekund, czeka na zwolnienie blokady, a następnie uzyskuje własną blokadę. W związku z tym przepływ jest serializowany.
@Component
public class Repository {
@PersistenceContext
private EntityManager em;
public Optional<Cache> getById(int id){
List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
.setParameter(1, id)
.setHint("javax.persistence.lock.timeout", 15000)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.getResultList();
return Optional.ofNullable(list.get(0));
}
public void save(Cache cache) {
cache = em.find(Cache.class, cache.getId());
em.merge(cache);
}
}
Upewnij się, że ten mechanizm blokady znajduje się wewnątrz transakcji, ponieważ blokada zostanie zwolniona, gdy transakcja zostanie zatwierdzona lub wycofana.