Para Spring Data 1.6 o superior
@Lock
es compatible con los métodos CRUD a partir de la versión 1.6 de Spring Data JPA (de hecho, ya existe un hito
disponible). Ver este boleto
para más detalles.
Con esa versión simplemente declaras lo siguiente:
interface WidgetRepository extends Repository<Widget, Long> {
@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 LockModeType configurado al find(…)
llama al EntityManager
.
Por otro lado,
Para la versión anterior de Spring Data 1.6
El @Lock
pesimista de Spring Data 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 a findByOne
con un bloqueo pesimista o puede 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ía crear algún administrador de bloqueo estático que tuviera un ThreadLocal<LockMode>
miembro variable y luego tener un aspecto envuelto alrededor de cada método en cada repositorio que llamó a bindResource con el modo de bloqueo establecido en ThreadLocal. Esto le permitiría configurar el modo de bloqueo por subproceso. Luego podría crear su propio @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.
Enlace de recursos:
- ¿Cómo habilitar LockModeType.PESSIMISTIC_WRITE al buscar entidades con Spring Data JPA?
- Cómo agregar un método personalizado método para Spring Data JPA
- Tiempo de espera de Spring Data Pessimistic Lock con Postgres
- API de consulta JPA
Varios ejemplos de tiempo de espera de bloqueo pesimista
Establecer un bloqueo pesimista
Un objeto de entidad se puede bloquear explícitamente mediante el método de bloqueo:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
El primer argumento es un objeto de entidad. El segundo argumento es el modo de bloqueo solicitado.
Una TransactionRequiredException
se lanza si no hay una transacción activa cuando se llama al bloqueo porque el bloqueo explícito requiere una transacción activa.
Una LockTimeoutException
se lanza si no se puede otorgar el bloqueo pesimista solicitado:
- UN
PESSIMISTIC_READ
la solicitud de bloqueo falla si otro usuario (que está representado por otra instancia de EntityManager) actualmente tiene unPESSIMISTIC_WRITE
bloqueo en ese objeto de la base de datos. - UN
PESSIMISTIC_WRITE
la solicitud de bloqueo falla si otro usuario actualmente tiene unPESSIMISTIC_WRITE
candado o unPESSIMISTIC_READ
bloquear ese objeto de la base de datos.
Configuración de la sugerencia de consulta (ámbitos)
Las sugerencias de consulta se pueden establecer en los siguientes ámbitos (de global a local):
Para toda la unidad de persistencia, usando un persistence.xml
propiedad:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Para una EntityManagerFactory - usando createEntityManagerFacotory
método:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Para un EntityManager:usando createEntityManager
método:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
o usando el método setProperty:
em.setProperty("javax.persistence.query.timeout", 6000);
Para una named query
definición - usando las hints
elemento:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Para una ejecución de consulta específica, usando setHint
método (antes de la ejecución de la consulta):
query.setHint("javax.persistence.query.timeout", 8000);