Oracle
 sql >> Database >  >> RDS >> Oracle

Differenza tra LockModeType Jpa

Per prima cosa distinguerei tra blocchi ottimisti e pessimisti, perché sono diversi nel loro meccanismo sottostante.

Il blocco ottimistico è completamente controllato da JPA e richiede solo una colonna versione aggiuntiva nelle tabelle DB. È completamente indipendente dal motore DB sottostante utilizzato per memorizzare i dati relazionali.

D'altra parte, il blocco pessimistico utilizza il meccanismo di blocco fornito dal database sottostante per bloccare i record esistenti nelle tabelle. JPA deve sapere come attivare questi blocchi e alcuni database non li supportano o li supportano solo in parte.

Ora all'elenco dei tipi di blocco:

  1. LockModeType.Optimistic
    • Se le entità specificano un campo versione, questo è il valore predefinito. Per le entità senza una colonna di versione, l'utilizzo di questo tipo di blocco non è garantito per funzionare su qualsiasi implementazione JPA. Questa modalità viene solitamente ignorata come indicato da ObjectDB. Secondo me esiste solo in modo che tu possa calcolare la modalità di blocco in modo dinamico e passarla ulteriormente anche se alla fine il blocco sarebbe OTTIMISTICO. Caso d'uso non molto probabile, tuttavia, ma è sempre una buona progettazione dell'API fornire un'opzione per fare riferimento anche al valore predefinito.
  • Esempio:

       `LockModeType lockMode = resolveLockMode();
     A a = em.find(A.class, 1, lockMode);`
    
  1. LockModeType.OPTIMISTIC_FORCE_INCREMENT
  • Questa è un'opzione usata raramente. Ma potrebbe essere ragionevole, se si desidera bloccare il riferimento a questa entità con un'altra entità. In altre parole, vuoi bloccare il lavoro con un'entità anche se non è stata modificata, ma altre entità possono essere modificate in relazione a questa entità.
  • Esempio:abbiamo l'entità Book and Shelf. È possibile aggiungere Book to Shelf, ma il libro non ha alcun riferimento al suo scaffale. È ragionevole bloccare l'azione di spostamento di un libro su uno scaffale, in modo che un libro non finisca in un altro scaffale (a causa di un'altra transazione) prima della fine di questa transazione. Per bloccare questa azione, non è sufficiente bloccare l'entità dello scaffale del libro corrente, poiché il libro non deve essere ancora su uno scaffale. Inoltre, non ha senso bloccare tutti gli scaffali di destinazione, poiché probabilmente sarebbero diversi in transazioni diverse. L'unica cosa che ha senso è bloccare l'entità libro stessa, anche se nel nostro caso non viene modificata (non tiene riferimento alla sua libreria).
  1. LockModeType.PESSIMISTIC_READ
  • questa modalità è simile a LockModeType.PESSIMISTIC_WRITE , ma diverso in una cosa:fino a quando il blocco di scrittura non è in atto sulla stessa entità da una transazione, non dovrebbe bloccare la lettura dell'entità. Consente inoltre di bloccare altre transazioni utilizzando LockModeType.PESSIMISTIC_READ . Le differenze tra i blocchi WRITE e READ sono ben spiegate qui (ObjectDB) e qui (OpenJPA). Se un'entità è già bloccata da un'altra transazione, qualsiasi tentativo di bloccarla genererà un'eccezione. Questo comportamento può essere modificato per attendere un po' di tempo per il rilascio del blocco prima di generare un'eccezione e ripristinare la transazione. Per farlo, specifica il javax.persistence.lock.timeout suggerimento con il numero di millisecondi da attendere prima di generare l'eccezione. Esistono diversi modi per farlo su più livelli, come descritto nel tutorial Java EE.
  1. LockModeType.PESSIMISTIC_WRITE
  • questa è una versione più potente di LockModeType.PESSIMISTIC_READ . Quando WRITE lock è in atto, JPA con l'aiuto del database impedirà a qualsiasi altra transazione di leggere l'entità, non solo di scrivere come con READ serratura.
  • Il modo in cui ciò viene implementato in un provider JPA in collaborazione con il DB sottostante non è prescritto. Nel tuo caso con Oracle, direi che Oracle non fornisce qualcosa di simile a un READ serratura. SELECT...FOR UPDATE è in realtà piuttosto un WRITE serratura. Potrebbe trattarsi di un bug in ibernazione o semplicemente di una decisione che, invece di implementare personalizzato "più morbido" READ lock, il WRITE "più difficile". invece viene utilizzato il blocco. Questo per lo più non interrompe la coerenza, ma non mantiene tutte le regole con READ serrature. Potresti eseguire dei semplici test con READ lock e transazioni di lunga durata per scoprire se più transazioni sono in grado di acquisire READ blocca la stessa entità. Questo dovrebbe essere possibile, mentre non con WRITE serrature.
  1. LockModeType.PESSIMISTIC_FORCE_INCREMENT
  • questa è un'altra modalità di blocco usata raramente. Tuttavia, è un'opzione in cui è necessario combinare PESSIMISTIC e OPTIMISTIC meccanismi. Usando un semplice PESSIMISTIC_WRITE fallirebbe nel seguente scenario:
    1. la transazione A utilizza il blocco ottimistico e legge l'entità E
    2. la transazione B acquisisce il blocco WRITE sull'entità E
    3. la transazione B esegue il commit e rilascia il blocco di E
    4. la transazione A aggiorna E e si impegna
  • al passaggio 4, se la colonna della versione non viene incrementata dalla transazione B, nulla impedisce ad A di sovrascrivere le modifiche di B. Modalità di blocco LockModeType.PESSIMISTIC_FORCE_INCREMENT forzerà la transazione B ad aggiornare il numero di versione e provocherà il fallimento della transazione A con OptimisticLockException , anche se B stava usando il blocco pessimistico.
  1. LockModeType.NONE
  • questa è l'impostazione predefinita se le entità non forniscono un campo versione. Significa che nessun blocco è abilitato, i conflitti verranno risolti sulla base del miglior sforzo e non verranno rilevati. Questa è l'unica modalità di blocco consentita al di fuori di una transazione