javax.persistence.lock.timeout също не трябва да работи за мен, когато е предоставен по-долу
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})
Но след това опитах нещо друго, което проработи. Вместо да използвам @Repository и CrudRepository, сега конфигурирам хибернацията си с помощта на мениджъра на обекти. Използва се createQuery заедно с времето за изчакване за заключване и задаване на заключване. И тази конфигурация работи според очакванията. Имам две транзакции, изпълнявани паралелно и опитващи се да заключат точно същия ред в DB. Първата транзакция може да получи заключване WRITE и задържа заключването за около 10 секунди, преди да освободи заключването. Междувременно втората транзакция се опитва да получи заключване на същия ред, но тъй като javax.persistence.lock.timeout е зададено на 15 секунди, тя изчаква заключването да бъде освободено и след това придобива собствено заключване. Следователно потокът се сериализира.
@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);
}
}
Уверете се, че този механизъм за заключване е вътре в транзакция, защото заключването ще бъде освободено, когато транзакция бъде извършена или върната назад.