Optimistické blokovanie v JPA

1. Úvod

Pokiaľ ide o podnikové aplikácie, je nevyhnutné správne spravovať súbežný prístup k databáze. To znamená, že by sme mali byť schopní vybaviť viac transakcií efektívnym a hlavne bezchybným spôsobom.

A čo viac, musíme zabezpečiť, aby údaje zostali konzistentné medzi súbežnými čítaniami a aktualizáciami.

Aby sme to dosiahli, môžeme použiť optimistický uzamykací mechanizmus poskytovaný rozhraním Java Persistence API. Vedie to k tomu, že viaceré aktualizácie vykonané na rovnakých dátach súčasne sa navzájom nerušia.

2. Pochopenie optimistického blokovania

Aby bolo možné použiť optimistické blokovanie, potrebujeme mať entitu zahŕňajúcu nehnuteľnosť s @ Verzia anotácia. Pri jeho použití má každá transakcia, ktorá číta dáta, hodnotu vlastnosti verzie.

Predtým, ako chce transakcia vykonať aktualizáciu, znova skontroluje vlastnosť verzie.

Ak sa medzitým hodnota zmenila, OptimisticLockException je hodená. V opačnom prípade sa transakcia zaviaže k aktualizácii a zvýši sa vlastnosť hodnotovej verzie.

3. Pesimistické zamykanie vs. optimistické zamykanie

Je dobré vedieť, že na rozdiel od optimistického zamykania nám JPA poskytuje pesimistické zamykanie. Je to ďalší mechanizmus na spracovanie súbežného prístupu k údajom.

Pesimistickému zamykaniu sa venujeme v jednom z našich predchádzajúcich článkov - Pesimistické zamykanie v JPA. Poďme zistiť, aký je rozdiel a ako môžeme ťažiť z každého typu uzamykania.

Ako sme už povedali, optimistické uzamykanie je založené na detekcii zmien na entitách kontrolou ich atribútu verzie. Ak dôjde k súbežnej aktualizácii, OptmisticLockException vyskytuje. Potom môžeme skúsiť aktualizovať údaje znova.

Vieme si predstaviť, že tento mechanizmus je vhodný pre aplikácie, ktoré oveľa viac čítajú ako aktualizujú alebo vymazávajú. Navyše je to užitočné v situáciách, keď musia byť entity určitý čas oddelené a zámky nemôžu byť zadržané.

Naopak, pesimistický zamykací mechanizmus zahŕňa zamykanie entít na úrovni databázy.

Každá transakcia môže získať blokovanie údajov. Pokiaľ drží zámok, nemôže žiadna transakcia čítať, mazať alebo vykonávať akékoľvek aktualizácie zamknutých údajov. Môžeme predpokladať, že použitie pesimistického blokovania môže mať za následok zablokovanie. Zaisťuje však väčšiu integritu údajov ako optimistické uzamykanie.

4. Atribúty verzie

Atribúty verzie sú vlastnosti s @ Verzia anotácia. Sú potrebné na umožnenie optimistického blokovania. Pozrime sa na ukážkovú triedu entít:

@Entity public class Student {@Id private Long id; súkromné ​​meno reťazca; private String priezvisko; @ Verzia verzie súkromného celého čísla; // zakladatelia a zakladatelia}

Pri deklarovaní atribútov verzie by sme sa mali riadiť niekoľkými pravidlami:

  • každá trieda entít musí mať iba jeden atribút verzie
  • musí byť umiestnený v primárnej tabuľke pre entitu namapovanú na niekoľko tabuliek
  • typ atribútu verzie musí byť jeden z nasledujúcich: int, Celé číslo, dlho, Dlhé, krátky, Krátky, java.sql.Timestamp

Mali by sme vedieť, že hodnotu atribútu verzie môžeme načítať prostredníctvom entity, ale nesmieme ju aktualizovať ani zvyšovať. Môže to urobiť iba poskytovateľ vytrvalosti, takže údaje zostanú konzistentné.

Stojí za povšimnutie, že poskytovatelia trvalosti sú schopní podporovať optimistické uzamykanie pre entity, ktoré nemajú atribúty verzie. Pri práci s optimistickým zamykaním je však dobré vždy zahrnúť atribúty verzie.

Ak sa pokúsime uzamknúť entitu, ktorá takýto atribút neobsahuje a poskytovateľ perzistencie ho nepodporuje, bude to mať za následok PersitenceException.

5. Uzamknite režimy

JPA nám poskytuje dva rôzne optimistické režimy uzamknutia (a dva aliasy):

  • OPTIMISTICKÝ - získava optimistický zámok čítania pre všetky entity obsahujúce atribút verzie
  • OPTIMISTIC_FORCE_INCREMENT - získa optimistický zámok ako OPTIMISTICKÝ a navyše zvyšuje hodnotu atribútu verzie
  • ČÍTAŤ - je to synonymum pre OPTIMISTICKÝ
  • NAPÍŠTE - je to synonymum pre OPTIMISTIC_FORCE_INCREMENT

Všetky typy uvedené vyššie nájdeme v LockModeType trieda.

5.1. OPTIMISTICKÝ (ČÍTAŤ)

Ako už vieme, OPTIMISTICKÝ a ČÍTAŤ režimy uzamknutia sú synonymá. Špecifikácia JPA nám však odporúča použitie OPTIMISTICKÝ v nových aplikáciách.

Kedykoľvek požadujeme OPTIMISTICKÝ uzamknutý režim, poskytovateľ vytrvalosti zabráni našim údajom v špinavých aj neopakovateľných údajoch.

Zjednodušene povedané, malo by sa zabezpečiť, aby sa pri akejkoľvek transakcii nepodarilo vykonať akúkoľvek úpravu údajov, ktoré iná transakcia vykonala:

  • sa aktualizoval alebo vymazal, ale nebol potvrdený
  • sa medzitým úspešne aktualizoval alebo vymazal

5.2. OPTIMISTIC_INCREMENT (NAPÍŠTE)

Rovnako ako predtým, OPTIMISTIC_INCREMENT a NAPÍŠTE sú synonymá, ale prvé je vhodnejšie.

OPTIMISTIC_INCREMENT musí spĺňať rovnaké podmienky ako OPTIMISTICKÝ režim uzamknutia. Ďalej zvyšuje hodnotu atribútu verzie. Nie je však špecifikované, či by sa to malo urobiť okamžite, alebo či sa dá odložiť, kým sa nespustí alebo nezaplní.

Je potrebné vedieť, že poskytovateľ perzistencie je oprávnený poskytovať OPTIMISTIC_INCREMENT funkčnosť keď OPTIMISTICKÝ požaduje sa režim uzamknutia.

6. Používanie optimistického blokovania

Mali by sme pamätať na to, že pre verzované entity je v predvolenom nastavení k dispozícii optimistické uzamykanie. Existuje niekoľko spôsobov, ako o to výslovne požiadať.

6.1. Nájsť

Na požiadanie o optimistické uzamknutie môžeme odovzdať správne LockModeType ako argument na nájdenie metódy EntityManager:

entityManager.find (Student.class, studentId, LockModeType.OPTIMISTIC);

6.2. Dopyt

Ďalším spôsobom, ako povoliť zamykanie, je použitie setLockMode metóda Dopyt objekt:

Dotaz na dotaz = entityManager.createQuery ("od študenta, kde id =: id"); query.setParameter ("id", studentId); query.setLockMode (LockModeType.OPTIMISTIC_INCREMENT); query.getResultList ()

6.3. Explicitné zamykanie

Zámok môžeme nastaviť volaním EnitityManager zámok metóda:

Student student = entityManager.find (Student.class, id); entityManager.lock (študent, LockModeType.OPTIMISTIC);

6.4. Obnoviť

Môžeme zavolať Obnoviť rovnakým spôsobom ako predchádzajúca metóda:

Student student = entityManager.find (Student.class, id); entityManager.refresh (študent, LockModeType.READ);

6.5. NamedQuery

Poslednou možnosťou je použiť @NamedQuery s lockMode nehnuteľnosť:

@NamedQuery (name = "optimisticLock", query = "VYBERTE S FROM študenta KDE s.id LIKE: id", lockMode = WRITE)

7. OptimisticLockException

Keď poskytovateľ perzistencie objaví optimistické zamykacie konflikty na entitách, hodí sa to OptimisticLockException. Mali by sme si uvedomiť, že z dôvodu výnimky je aktívna transakcia vždy označená ako rollback.

Je dobré vedieť, ako môžeme reagovať OptimisticLockException. Táto výnimka účelne obsahuje odkaz na konfliktnú entitu. Poskytovateľ vytrvalosti však nie je povinný dodávať ho v každej situácii. Nie je zaručené, že objekt bude k dispozícii.

Existuje však odporúčaný spôsob zaobchádzania s opísanou výnimkou. Subjekt by sme mali znovu načítať načítaním alebo obnovením. Najlepšie v novej transakcii. Potom sa môžeme pokúsiť ešte raz aktualizovať.

8. Záver

V tomto tutoriáli sme sa oboznámili s nástrojom, ktorý nám môže pomôcť orchestrovať súbežné transakcie. Optimistické uzamykanie používa atribúty verzie zahrnuté v entitách na riadenie súbežných úprav na nich.

Preto zaisťuje, že žiadne aktualizácie ani mazania nebudú prepísané alebo stratené potichu. Oproti pesimistickému zamykaniu nezamyká entity na úrovni databázy a v dôsledku toho nie je zraniteľný voči zablokovaniu DB.

Dozvedeli sme sa, že optimistické zamykanie je pre verzované entity predvolene povolené. Existuje však niekoľko spôsobov, ako o to výslovne požiadať, a to pomocou rôznych typov režimu uzamknutia.

Ďalšou skutočnosťou, ktorú by sme si mali pamätať, je, že vždy, keď dôjde k protichodným aktualizáciám entít, mali by sme očakávať OptimisticLockException.

Nakoniec je zdrojový kód tohto tutoriálu k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found