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_READa solicitação de bloqueio falhará se outro usuário (representado por outra instância do EntityManager) tiver umPESSIMISTIC_WRITElock nesse objeto de banco de dados. - Um
PESSIMISTIC_WRITEa solicitação de bloqueio falhará se outro usuário possuir umPESSIMISTIC_WRITEbloqueio ou umPESSIMISTIC_READbloquear 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);