Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Diferença entre LockModeType Jpa


Eu primeiro diferenciaria entre bloqueios otimistas e pessimistas, porque eles são diferentes em seu mecanismo subjacente.

O bloqueio otimista é totalmente controlado pelo JPA e requer apenas uma coluna de versão adicional nas tabelas de banco de dados. É completamente independente do mecanismo de banco de dados subjacente usado para armazenar dados relacionais.

Por outro lado, o bloqueio pessimista usa o mecanismo de bloqueio fornecido pelo banco de dados subjacente para bloquear os registros existentes nas tabelas. O JPA precisa saber como acionar esses bloqueios e alguns bancos de dados não os suportam ou os suportam apenas parcialmente.

Agora para a lista de tipos de bloqueio:
  1. LockModeType.Optimistic
    • Se as entidades especificarem um campo de versão, este será o padrão. Para entidades sem uma coluna de versão, não é garantido que o uso desse tipo de bloqueio funcione em qualquer implementação de JPA. Esse modo geralmente é ignorado conforme declarado pelo ObjectDB. Na minha opinião, ele só existe para que você possa calcular o modo de bloqueio dinamicamente e passá-lo ainda mais, mesmo que o bloqueio seja OTIMISTA no final. No entanto, não é um caso de uso muito provável, mas é sempre um bom design de API fornecer uma opção para referenciar até mesmo o valor padrão.

  • Exemplo:
       `LockModeType lockMode = resolveLockMode();
     A a = em.find(A.class, 1, lockMode);`
    
  1. LockModeType.OPTIMISTIC_FORCE_INCREMENT
  • Esta é uma opção raramente usada. Mas pode ser razoável, se você quiser bloquear a referência a essa entidade por outra entidade. Em outras palavras, você deseja bloquear o trabalho com uma entidade mesmo que ela não seja modificada, mas outras entidades podem ser modificadas em relação a essa entidade.
  • Exemplo:temos a entidade Book and Shelf. É possível adicionar Livro à Estante, mas o livro não tem nenhuma referência à sua estante. É razoável bloquear a ação de mover um livro para uma estante, para que um livro não acabe em outra estante (devido a outra transação) antes do final desta transação. Para bloquear esta ação, não é suficiente bloquear a entidade da estante de livros atual, pois o livro ainda não precisa estar em uma estante. Também não faz sentido bloquear todas as estantes de destino, pois elas provavelmente seriam diferentes em transações diferentes. A única coisa que faz sentido é bloquear a própria entidade do livro, mesmo que no nosso caso ela não seja alterada (ela não mantém referência à sua estante).
  1. LockModeType.PESSIMISTIC_READ
  • este modo é semelhante a LockModeType.PESSIMISTIC_WRITE , mas diferente em uma coisa:até que o bloqueio de gravação esteja em vigor na mesma entidade por alguma transação, ele não deve bloquear a leitura da entidade. Ele também permite que outras transações sejam bloqueadas usando LockModeType.PESSIMISTIC_READ . As diferenças entre os bloqueios WRITE e READ são bem explicadas aqui (ObjectDB) e aqui (OpenJPA). Se uma entidade já estiver bloqueada por outra transação, qualquer tentativa de bloqueá-la lançará uma exceção. Esse comportamento pode ser modificado para aguardar algum tempo para que o bloqueio seja liberado antes de lançar uma exceção e reverter a transação. Para fazer isso, especifique o javax.persistence.lock.timeout dica com o número de milissegundos a esperar antes de lançar a exceção. Há várias maneiras de fazer isso em vários níveis, conforme descrito no tutorial Java EE.
  1. LockModeType.PESSIMISTIC_WRITE
  • esta é uma versão mais forte de LockModeType.PESSIMISTIC_READ . Quando WRITE lock está em vigor, JPA com a ajuda do banco de dados impedirá qualquer outra transação de ler a entidade, não apenas para escrever como com READ bloqueio.
  • A maneira como isso é implementado em um provedor JPA em cooperação com o banco de dados subjacente não é prescrita. No seu caso com o Oracle, eu diria que o Oracle não fornece algo próximo a um READ trancar. SELECT...FOR UPDATE é realmente um WRITE trancar. Pode ser um bug na hibernação ou apenas uma decisão que, em vez de implementar o READ personalizado "mais suave" lock, o "mais difícil" WRITE bloqueio é usado em seu lugar. Isso geralmente não quebra a consistência, mas não mantém todas as regras com READ fechaduras. Você pode executar alguns testes simples com READ bloqueios e transações de longa duração para descobrir se mais transações podem adquirir READ bloqueios na mesma entidade. Isso deve ser possível, mas não com WRITE fechaduras.
  1. LockModeType.PESSIMISTIC_FORCE_INCREMENT
  • este é outro modo de bloqueio raramente usado. No entanto, é uma opção onde você precisa combinar PESSIMISTIC e OPTIMISTIC mecanismos. Usando PESSIMISTIC_WRITE simples falharia no seguinte cenário:
    1. transação A usa bloqueio otimista e lê a entidade E
    2. transação B adquire bloqueio WRITE na entidade E
    3. transação B confirma e libera bloqueio de E
    4. transação A atualiza E e confirma
  • na etapa 4, se a coluna de versão não for incrementada pela transação B, nada impedirá que A substitua as alterações de B. Modo de bloqueio LockModeType.PESSIMISTIC_FORCE_INCREMENT forçará a transação B a atualizar o número da versão e fará com que a transação A falhe com OptimisticLockException , embora B estivesse usando um bloqueio pessimista.
  1. LockModeType.NONE
  • este é o padrão se as entidades não fornecerem um campo de versão. Isso significa que nenhum bloqueio está habilitado os conflitos serão resolvidos com base no melhor esforço e não serão detectados. Este é o único modo de bloqueio permitido fora de uma transação