java - query - spring data jpa jpql
Datos de primavera CrudRepository y bloqueo pesimista (1)
Estoy usando
- Bota de primavera 1.4.2
- Datos de primavera JPA 1.10.5
- Base de datos PostgreSQL 9.5
Quiero tener un método findOne
con bloqueo pesimista en mi repositorio de datos de Spring que sea independiente del método findOne
que ya se proporcionó.
Siguiendo esta respuesta escribí:
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);
}
Esto casi funciona.
Desafortunadamente, esto no actualiza la instancia anterior de mi entidad en el caché del administrador de entidades. Tengo dos solicitudes simultáneas actualizando el estado de mi registro
- el segundo espera a que se comprometa la transacción del primero
- El segundo no tiene en cuenta los cambios realizados por el primero.
De ahí el comportamiento roto.
¿Alguna pista de por qué @Lock
no actualiza el administrador de entidades?
Actualizar
Aquí está el código de ejemplo solicitado:
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);
}
}
Necesitas usar la entityManger transaction
que Spring
crea para ti:
@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);
}
}