Nejprve bych rozlišoval mezi optimistickými a pesimistickými zámky, protože se liší svým základním mechanismem.
Optimistické zamykání je plně řízeno JPA a vyžaduje pouze další sloupec verze v tabulkách DB. Je zcela nezávislý na základním DB engine používaném k ukládání relačních dat.
Na druhou stranu pesimistické zamykání používá zamykací mechanismus poskytovaný podkladovou databází k uzamčení existujících záznamů v tabulkách. JPA potřebuje vědět, jak spouštět tyto zámky a některé databáze je nepodporují nebo jen částečně.
Nyní k seznamu typů zámků:
LockModeType.Optimistic- Pokud entity specifikují pole verze, jedná se o výchozí hodnotu. U entit bez sloupce verze není zaručeno, že použití tohoto typu zámku bude fungovat v jakékoli implementaci JPA. Tento režim je obvykle ignorován, jak uvádí ObjectDB. Podle mého názoru existuje pouze proto, abyste mohli dynamicky vypočítat režim zámku a předat jej dále, i když by zámek byl nakonec OPTIMISTICKÝ. Není to sice příliš pravděpodobné použití, ale vždy je dobrý návrh API poskytnout možnost odkazovat i na výchozí hodnotu.
-
Příklad:
`LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);`
LockModeType.OPTIMISTIC_FORCE_INCREMENT
- Toto je zřídka používaná možnost. Ale mohlo by to být rozumné, pokud chcete uzamknout odkazování na tuto entitu jinou entitou. Jinými slovy, chcete zamknout práci s entitou, i když není upravena, ale jiné entity mohou být ve vztahu k této entitě upraveny.
- Příklad:Máme entitu Book and Shelf. Je možné přidat knihu do police, ale kniha nemá žádný odkaz na svou polici. Je rozumné uzamknout přesun knihy na polici, aby kniha neskončila v jiné polici (kvůli jiné transakci) před ukončením této transakce. K uzamčení této akce nestačí uzamknout aktuální entitu police s knihami, protože kniha ještě nemusí být na poličce. Také nemá smysl zamykat všechny cílové knihovny, protože by se pravděpodobně v různých transakcích lišily. Jediná věc, která dává smysl, je uzamknout samotnou entitu knihy, i když se v našem případě nezmění (neobsahuje odkaz na svou knihovnu).
LockModeType.PESSIMISTIC_READ
- tento režim je podobný režimu
LockModeType.PESSIMISTIC_WRITE, ale v jedné věci se liší:dokud není na stejné entitě nějakou transakcí nasazen zámek zápisu, nemělo by to blokovat čtení entity. Umožňuje také uzamknout další transakce pomocíLockModeType.PESSIMISTIC_READ. Rozdíly mezi zámky WRITE a READ jsou dobře vysvětleny zde (ObjectDB) a zde (OpenJPA). Pokud je entita již uzamčena jinou transakcí, jakýkoli pokus o její uzamčení vyvolá výjimku. Toto chování lze upravit tak, aby před vyvoláním výjimky a vrácením transakce nějakou dobu čekalo na uvolnění zámku. Chcete-li to provést, zadejtejavax.persistence.lock.timeoutnápověda s počtem milisekund před vyvoláním výjimky. Existuje několik způsobů, jak toho dosáhnout na několika úrovních, jak je popsáno v tutoriálu Java EE.
LockModeType.PESSIMISTIC_WRITE
- toto je silnější verze
LockModeType.PESSIMISTIC_READ. KdyžWRITEzámek je na svém místě, JPA s pomocí databáze zabrání jakékoli jiné transakci čtení entity, nejen zápisu jako uREADzámek. - Způsob, jak je to implementováno u poskytovatele JPA ve spolupráci s podkladovou DB, není předepsáno. Ve vašem případě Oracle bych řekl, že Oracle neposkytuje něco blízkého
READzámek.SELECT...FOR UPDATEje ve skutečnosti spíšeWRITEzámek. Může to být chyba v hibernaci nebo jen rozhodnutí, které namísto implementace vlastního "měkčího"READzámek, "tvrdší"WRITEmísto toho se používá zámek. To většinou nenarušuje konzistenci, ale nedrží všechna pravidla sREADzámky. Můžete spustit několik jednoduchých testů pomocíREADzámky a dlouhotrvající transakce, abyste zjistili, zda je více transakcí schopno získatREADzámky na stejnou entitu. To by mělo být možné, ale ne pomocíWRITEzámky.
- LockModeType.PESSIMISTIC_FORCE_INCREMENT
- toto je další zřídka používaný režim uzamčení. Je to však možnost, kde je potřeba kombinovat
PESSIMISTICaOPTIMISTICmechanismy. Pomocí prostéhoPESSIMISTIC_WRITEselže v následujícím scénáři:- transakce A používá optimistické zamykání a čte entitu E
- transakce B získá zámek WRITE na entitě E
- transakce B potvrdí a uvolní zámek E
- transakce A aktualizuje E a odevzdá
- Pokud v kroku 4 není sloupec verze zvýšen o transakci B, nic nebrání A v přepsání změn B. Režim zámku
LockModeType.PESSIMISTIC_FORCE_INCREMENTvynutí transakci B k aktualizaci čísla verze a způsobí selhání transakce A sOptimisticLockException, i když B používal pesimistické zamykání.
- LockModeType.NONE
- toto je výchozí hodnota, pokud entity neposkytují pole verze. To znamená, že není povoleno žádné zamykání, konflikty budou vyřešeny na základě maximálního úsilí a nebudou detekovány. Toto je jediný režim uzamčení povolený mimo transakci