Подтвердить что ты не робот

Spring данные CrudRepository и пессимистическая блокировка

Я использую

  • Spring Загрузка 1.4.2
  • Spring Данные JPA 1.10.5
  • База данных PostgreSQL 9.5

Я хочу иметь метод findOne с пессимистической блокировкой в ​​моем репозитории данных Spring, который отделен от метода findOne, который уже предоставлен.

Следуя этому ответу, я написал:

public interface RegistrationRepository extends CrudRepository<Registration, Long> {
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select r from Registration r where r.id = ?1")
    Registration findOnePessimistic(Long id);
}

Это почти работает.

К сожалению, это не обновляет предыдущий экземпляр моего объекта в кеше менеджера объектов. У меня есть два одновременных запроса, обновляющих статус моей регистрации.

  • второй ожидает транзакции первого, кто совершит
  • второй не учитывает изменения, сделанные первым.

Следовательно, нарушение поведения.

Любая подсказка, почему @Lock не из окна обновить диспетчер сущностей?

Update

Вот запрошенный пример кода:

public interface RegistrationRepository extends CrudRepository<Registration, Long> {

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select r from registration_table r where r.id = ?1")
    Registration findOnePessimistic(Long id);

}

public void RegistrationService {

    @Transactional
    public void doSomething(long id){
        // Both threads read the same version of the data 
        Registration registrationQueriedTheFirstTime = registrationRepository.findOne(id);

        // First thread gets the lock, second thread waits for the first thread to have committed
        Registration registration = registrationRepository.findOnePessimistic(id);
        // I need this to have this statement, otherwise, registration.getStatus() contains the value not yet updated by the first thread
        entityManager.refresh(registration);

        registration.setStatus(newStatus);
        registrationRepository.save(registration);
    }
}
4b9b3361

Ответ 1

Вам нужно использовать entityManger transaction, который Spring создает для вас:

    @Transactional
    public void doSomething(long id){
        // Both threads read the same version of the data 
        Registration registrationQueriedTheFirstTime = registrationRepository.findOne(id);

        // First thread gets the lock, second thread waits for the first thread to have committed
        Registration registration = registrationRepository.findOnePessimistic(id);
        // I need this to have this statement, otherwise, registration.getStatus() contains the value not yet updated by the first thread
        entityManager.refresh(registration);

        EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(<Your entity manager factory>);
        em.refresh(registration);
        registration.setStatus(newStatus);
        registrationRepository.save(registration);
    }

}