update query jparepository delete data crudrepository java spring spring-data spring-data-jpa

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); } }