Saltar al contenido

¿Cómo habilitar LockModeType.PESSIMISTIC_WRITE al buscar entidades con Spring Data JPA?

Sé libre de compartir nuestra web y códigos con otro, necesitamos tu ayuda para aumentar esta comunidad.

Solución:

@Lock es compatible con los métodos CRUD a partir de la versión 1.6 de Spring Data JPA (de hecho, ya hay un hito disponible). Ver este boleto para más detalles.

Con esa versión simplemente declaras lo siguiente:

interface WidgetRepository extends Repository 

  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Widget findOne(Long id);

Esto hará que la parte de implementación de CRUD del proxy del repositorio de respaldo aplique el configurado LockModeType al find(…) llamar a la EntityManager.

Si no desea anular el estándar findOne() método, puede adquirir un bloqueo en su método personalizado utilizando select ... for update consulta así:

/**
 * Repository for Wallet.
 */
public interface WalletRepository extends CrudRepository, JpaSpecificationExecutor 

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select w from Wallet w where w.id = :id")
    Wallet findOneForUpdate(@Param("id") Long id);

Sin embargo, si está utilizando PostgreSQL, las cosas pueden complicarse un poco cuando desea configurar el tiempo de espera de bloqueo para evitar interbloqueos. PostgreSQL ignora la propiedad estándar javax.persistence.lock.timeout establecido en propiedades JPA o en @QueryHint anotación.

La única forma en que podía hacerlo funcionar era crear un repositorio personalizado y configurar el tiempo de espera manualmente antes de bloquear una entidad. No es agradable, pero al menos funciona:

public class WalletRepositoryImpl implements WalletRepositoryCustom 

@PersistenceContext
private EntityManager em;


@Override
public Wallet findOneForUpdate(Long id) 
    // explicitly set lock timeout (necessary in PostgreSQL)
    em.createNativeQuery("set local lock_timeout to '2s';").executeUpdate();

    Wallet wallet = em.find(Wallet.class, id);

    if (wallet != null) 
        em.lock(wallet, LockModeType.PESSIMISTIC_WRITE);
    

    return wallet;

Si puede usar Spring Data 1.6 o superior, ignore esta respuesta y consulte la respuesta de Oliver.

El pesimista Spring Data @Lock las anotaciones solo se aplican (como usted señaló) a las consultas. No hay anotaciones que yo sepa que puedan afectar una transacción completa. Puede crear un findByOnePessimistic método que llama findByOne con un candado pesimista o puedes cambiar findByOne para obtener siempre un bloqueo pesimista.

Si quisiera implementar su propia solución, probablemente podría hacerlo. Debajo del capó el @Lock la anotación es procesada por LockModePopulatingMethodIntercceptor que hace lo siguiente:

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);

Podrías crear algunos static administrador de bloqueo que tenía un ThreadLocal variable miembro y luego tener un aspecto envuelto alrededor de cada método en cada repositorio que llamó bindResource con el modo de bloqueo establecido en el ThreadLocal. Esto le permitiría configurar el modo de bloqueo por subproceso. A continuación, podría crear su propia @MethodLockMode anotación que envolvería el método en un aspecto que establece el modo de bloqueo específico del subproceso antes de ejecutar el método y lo borra después de ejecutar el método.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *