Habilitando bloqueios de transação no Spring Data JPA

Habilitando bloqueios de transação no Spring Data JPA

1. Visão geral

Neste tutorial rápido, discutiremos a ativação de bloqueios de transação no Spring Data JPA paracustom query methodse métodos CRUD de repositório predefinidos.

Também analisaremos os diferentes tipos de bloqueio e definiremos o tempo limite de bloqueio da transação.

2. Tipos de bloqueio

A JPA possui dois tipos principais de bloqueio definidos, que são Bloqueio Pessimista e Bloqueio Otimista.

2.1 Pessimistic Locking

When we are using Pessimistic Locking in a transaction and access an entity, it will be locked immediately. A transação libera o bloqueio confirmando ou revertendo a transação.

2.2 Optimistic Locking

In Optimistic Locking, the transaction doesn’t lock the entity immediately. Em vez disso, a transação normalmente salva o estado da entidade com um número de versão atribuído a ela.

Quando tentamos atualizar o estado da entidade em uma transação diferente, a transação compara o número da versão salva com o número da versão existente durante uma atualização.

Neste ponto, se o número da versão for diferente, significa que a entidade não pode ser modificada. Se houver uma transação ativa, essa transação será revertida e a implementação JPA subjacente lançará umOptimisticLockException.

Além da abordagem do número da versão, podemos usar outras abordagens, como carimbos de data e hora, computação com valor de hash ou soma de verificação serializada, dependendo da abordagem mais adequada ao nosso contexto de desenvolvimento atual.

3. Habilitando bloqueios de transação em métodos de consulta

Para adquirir um bloqueio em uma entidade, podemos anotar o método de consulta de destino com uma anotaçãoLock passando o tipo de modo de bloqueio necessário .

Lock mode types são valores enum a serem especificados ao bloquear uma entidade. O modo de bloqueio especificado é propagado para o banco de dados para aplicar o bloqueio correspondente no objeto da entidade.

Para especificar um bloqueio em um método de consulta personalizado de um repositório Spring Data JPA, podemos anotar o método com@Locke especificar o tipo de modo de bloqueio necessário:

@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("SELECT c FROM Customer c WHERE c.orgId = ?1")
public List fetchCustomersByOrgId(Long orgId);

Para impor o bloqueio em métodos de repositório predefinidos, comofindAll oufindById(id), temos que declarar o método dentro do repositório e anotar o método com a anotaçãoLock:

@Lock(LockModeType.PESSIMISTIC_READ)
public Optional findById(Long customerId);

Quando o bloqueio está explicitamente ativado e não há nenhuma transação ativa, a implementação JPA subjacente lançará umTransactionRequiredException.

Caso o bloqueio não possa ser concedido e o conflito de bloqueio não resulte em uma reversão de transação, JPA lança umLockTimeoutException. Mas não marca a transação ativa para reversão.

4. Definindo tempos limite de bloqueio de transação

Ao usar o bloqueio pessimista, o banco de dados tentará bloquear a entidade imediatamente. A implementação JPA subjacente emite umLockTimeoutException quando o bloqueio não pode ser obtido imediatamente. Para evitar essas exceções, podemos especificar o valor do tempo limite do bloqueio.

No Spring Data JPA, o tempo limite de bloqueio pode ser especificado usando a anotaçãoQueryHints colocando umQueryHint nos métodos de consulta:

@Lock(LockModeType.PESSIMISTIC_READ)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "3000")})
public Optional findById(Long customerId);

Mais detalhes sobre como definir a dica de tempo limite de bloqueio em diferentes escopos podem ser encontrados nesteObjectDB article.

5. Conclusão

Neste tutorial, aprendemos os diferentes tipos de modos de bloqueio de transação. Aprendemos como habilitar bloqueios de transação no Spring Data JPA. Também cobrimos a configuração de tempos limite de bloqueio.

A aplicação dos bloqueios de transação corretos nos locais certos pode ajudar a manter a integridade dos dados em aplicativos de uso simultâneo de alto volume.

Quando a transação precisa aderir estritamente às regras do ACID, devemos usar o bloqueio pessimista. O bloqueio otimista deve ser aplicado quando precisamos permitir várias leituras simultâneas e quando a consistência eventual é aceitável dentro do contexto do aplicativo.

Obviamente, o código de amostra para bloqueio pessimista e bloqueio otimista pode ser encontradoover on Github.