Para Spring Data 1.6 ou superior
@Lock
é suportado em métodos CRUD a partir da versão 1.6 do Spring Data JPA (na verdade, já existe um marco
acessível). Veja este ingresso
para mais detalhes. Com essa versão você simplesmente declara o seguinte:
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
Isso fará com que a parte de implementação CRUD do proxy do repositório de apoio aplique o LockModeType configurado ao
find(…)
chame o EntityManager
. Por outro lado,
Para a versão anterior do Spring Data 1.6
O pessimista do Spring Data
@Lock
as anotações só se aplicam (como você apontou) às consultas. Não há anotações que eu conheça que possam afetar uma transação inteira. Você pode criar um findByOnePessimistic
método que chama findByOne
com um bloqueio pessimista ou você pode alterar findByOne
obter sempre um bloqueio pessimista. Se você quisesse implementar sua própria solução, provavelmente conseguiria. Sob o capô, o
@Lock
a anotação é processada por LockModePopulatingMethodIntercceptor
que faz o seguinte:TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Você poderia criar algum gerenciador de bloqueio estático que tivesse um
ThreadLocal<LockMode>
member variável e, em seguida, ter um aspecto envolvido em cada método em cada repositório que chamou bindResource com o modo de bloqueio definido no arquivo ThreadLocal. Isso permitiria que você defina o modo de bloqueio por thread. Você pode então criar seu próprio @MethodLockMode
anotação que envolveria o método em um aspecto que define o modo de bloqueio específico do thread antes de executar o método e o limpa após executar o método. Link do recurso:
- Como habilitar LockModeType.PESSIMISTIC_WRITE ao pesquisar entidades com Spring Data JPA?
- Como adicionar personalizado método para Spring Data JPA
- Tempo limite de bloqueio pessimista do Spring Data com Postgres
- API de consulta JPA
Vários exemplos de tempo limite de bloqueio pessimista
Definindo um bloqueio pessimista
Um objeto de entidade pode ser bloqueado explicitamente pelo método de bloqueio:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
O primeiro argumento é um objeto de entidade. O segundo argumento é o modo de bloqueio solicitado.
Uma
TransactionRequiredException
é lançado se não houver nenhuma transação ativa quando o bloqueio for chamado porque o bloqueio explícito requer uma transação ativa. Uma
LockTimeoutException
é lançado se o bloqueio pessimista solicitado não puder ser concedido:- Um
PESSIMISTIC_READ
a solicitação de bloqueio falhará se outro usuário (representado por outra instância do EntityManager) tiver umPESSIMISTIC_WRITE
lock nesse objeto de banco de dados. - Um
PESSIMISTIC_WRITE
a solicitação de bloqueio falhará se outro usuário possuir umPESSIMISTIC_WRITE
bloqueio ou umPESSIMISTIC_READ
bloquear nesse objeto de banco de dados.
Definindo a dica de consulta (escopos)
As dicas de consulta podem ser definidas nos seguintes escopos (de global a local):
Para toda a unidade de persistência - usando um
persistence.xml
propriedade:<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Para um EntityManagerFactory - usando o
createEntityManagerFacotory
método:Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Para um EntityManager - usando o
createEntityManager
método:Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
ou usando o método setProperty:
em.setProperty("javax.persistence.query.timeout", 6000);
Para uma
named query
definição - usando as hints
elemento:@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Para uma execução de consulta específica - usando o
setHint
método (antes da execução da consulta):query.setHint("javax.persistence.query.timeout", 8000);