Optimistisk låsing i JPA

1. Introduksjon

Når det gjelder bedriftsapplikasjoner, er det viktig å administrere samtidig tilgang til en database riktig. Dette betyr at vi skal kunne håndtere flere transaksjoner på en effektiv og viktigst, feilsikker måte.

I tillegg må vi sørge for at data forblir konsistente mellom samtidig lesing og oppdatering.

For å oppnå det kan vi bruke optimistisk låsemekanisme levert av Java Persistence API. Det fører til at flere oppdateringer som er gjort på de samme dataene samtidig ikke forstyrrer hverandre.

2. Forstå optimistisk låsing

For å bruke optimistisk låsing, vi må ha en enhet som inkluderer en eiendom med @Versjon kommentar. Mens du bruker den, inneholder hver transaksjon som leser data verdien av versjonsegenskapen.

Før transaksjonen ønsker å gjøre en oppdatering, sjekker den versjonsegenskapen igjen.

Hvis verdien har endret seg i mellomtiden, an OptimisticLockException blir kastet. Ellers forplikter transaksjonen oppdateringen og øker en verdiversjonsegenskap.

3. Pessimistisk låsing kontra optimistisk låsing

Det er godt å vite at i motsetning til optimistisk låsing gir JPA oss pessimistisk låsing. Det er en annen mekanisme for håndtering av samtidig tilgang for data.

Vi dekker pessimistisk låsing i en av våre tidligere artikler - Pessimistisk låsing i JPA. La oss finne ut hva som er forskjellen og hvordan vi kan dra nytte av hver type låsing.

Som vi har sagt før, optimistisk låsing er basert på å oppdage endringer på enheter ved å sjekke versjonsattributtet. Hvis noen samtidig oppdatering finner sted, OptmisticLockException inntreffer. Etter det kan vi prøve å oppdatere dataene på nytt.

Vi kan forestille oss at denne mekanismen er egnet for applikasjoner som gjør mye mer lesing enn oppdateringer eller sletting. Dessuten er det nyttig i situasjoner der enheter må være løsrevet i noen tid og låser ikke kan holdes.

Tvert imot innebærer pessimistisk låsemekanisme å låse enheter på databasenivå.

Hver transaksjon kan skaffe seg en lås på data. Så lenge det holder låsen, kan ingen transaksjoner lese, slette eller gjøre oppdateringer på de låste dataene. Vi kan anta at bruk av pessimistisk låsing kan føre til fastlåsning. Imidlertid sørger det for større integritet av data enn optimistisk låsing.

4. Versjonsattributter

Versjonsattributter er egenskaper med @Versjon kommentar. De er nødvendige for å muliggjøre optimistisk låsing. La oss se et eksempel på en enhetsklasse:

@Entity offentlig klasse Student {@Id privat Lang id; privat strengnavn; privat streng etternavn; @Version privat heltalversjon; // getters og setters}

Det er flere regler som vi bør følge når vi erklærer versjonsattributter:

  • hver enhetsklasse må bare ha ett versjonsattributt
  • den må plasseres i primærtabellen for en enhet som er kartlagt til flere tabeller
  • type versjonsattributt må være ett av følgende: int, Heltall, lang, Lang, kort, Kort, java.sql.Tidsstempel

Vi bør vite at vi kan hente en verdi av versjonsattributtet via enhet, men vi må ikke oppdatere eller øke den. Bare vedvarende leverandør kan gjøre det, slik at data forblir konsistente.

Det er verdt å merke seg at utholdenhetsleverandører kan støtte optimistisk låsing for enheter som ikke har versjonsattributter. Likevel er det en god ide å alltid inkludere versjonsattributter når du arbeider med optimistisk låsing.

Hvis vi prøver å låse en enhet som ikke inneholder et slikt attributt og utholdenhetsleverandøren ikke støtter det, vil det resultere i en PersitenceException.

5. Lås modus

JPA gir oss to forskjellige optimistiske låsemoduser (og to aliaser):

  • OPTIMISTISK - den får en optimistisk leselås for alle enheter som inneholder et versjonsattributt
  • OPTIMISTIC_FORCE_INCREMENT - det får en optimistisk lås det samme som OPTIMISTISK og øker i tillegg versjonsattributtverdien
  • LESE - det er et synonym for OPTIMISTISK
  • SKRIVE - det er et synonym for OPTIMISTIC_FORCE_INCREMENT

Vi finner alle typene som er oppført ovenfor i LockModeType klasse.

5.1. OPTIMISTISK (LESE)

Som vi allerede vet, OPTIMISTISK og LESE låsemodus er synonymer. Imidlertid anbefaler JPA-spesifikasjon oss å bruke OPTIMISTISK i nye applikasjoner.

Når vi ber om OPTIMISTISK låsemodus, vil en utholdenhetsleverandør forhindre at dataene våre blir skitne avlesninger så vel som ikke-repeterbare avlesninger.

Enkelt sagt, det skal sikre at enhver transaksjon ikke foretar endringer på data som en annen transaksjon:

  • har oppdatert eller slettet, men ikke forpliktet
  • har oppdatert eller slettet i mellomtiden

5.2. OPTIMISTIC_INCREMENT (SKRIVE)

Det samme som tidligere, OPTIMISTIC_INCREMENT og SKRIVE er synonymer, men førstnevnte er å foretrekke.

OPTIMISTIC_INCREMENT må oppfylle de samme vilkår som OPTIMISTISK låsemodus. I tillegg øker den verdien til et versjonsattributt. Det er imidlertid ikke spesifisert om det skal gjøres umiddelbart eller kan bli utsatt til det er begått eller spylt.

Det er verdt å vite at en utholdenhetsleverandør har lov til å tilby OPTIMISTIC_INCREMENT funksjonalitet når OPTIMISTISK låsemodus er bedt om.

6. Bruke optimistisk låsing

Vi bør huske at for versjonerte enheter er optimal låsing tilgjengelig som standard. Likevel er det flere måter å be om det eksplisitt.

6.1. Finne

For å be om optimistisk låsing kan vi passere riktig LockModeType som et argument for å finne metode for EntityManager:

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

6.2. Spørsmål

En annen måte å aktivere låsing på er å bruke setLockMode Metode av Spørsmål gjenstand:

Query query = entityManager.createQuery ("fra Student hvor id =: id"); query.setParameter ("id", studentId); query.setLockMode (LockModeType.OPTIMISTIC_INCREMENT); query.getResultList ()

6.3. Eksplisitt låsing

Vi kan sette en lås ved å ringe EnitityManager's låse metode:

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

6.4. Forfriske

Vi kan ringe forfriske metode på samme måte som forrige metode:

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

6.5. NamedQuery

Det siste alternativet er å bruke @NamedQuery med lockMode eiendom:

@NamedQuery (name = "optimisticLock", query = "SELECT s FRA Student s WHERE s.id LIKE: id", lockMode = WRITE)

7. OptimisticLockException

Når utholdenhetsleverandøren oppdager optimistiske låsekonflikter på enheter, kaster det OptimisticLockException. Vi bør være oppmerksom på at den aktive transaksjonen på grunn av unntaket alltid er merket for tilbakeføring.

Det er godt å vite hvordan vi kan reagere på OptimisticLockException. Dette unntaket inneholder beleilig en referanse til den motstridende enheten. Det er imidlertid ikke obligatorisk for utholdenhetsleverandøren å levere det i alle situasjoner. Det er ingen garanti for at objektet vil være tilgjengelig.

Det er imidlertid en anbefalt måte å håndtere det beskrevne unntaket på. Vi bør hente enheten igjen ved å laste inn eller oppdatere den på nytt. Gjerne i en ny transaksjon. Etter det kan vi prøve å oppdatere den en gang til.

8. Konklusjon

I denne opplæringen ble vi kjent med et verktøy som kan hjelpe oss med å organisere samtidige transaksjoner. Optimistisk låsing bruker versjonsattributter som er inkludert i enheter for å kontrollere samtidige modifikasjoner på dem.

Derfor sørger det for at oppdateringer eller slettinger ikke blir overskrevet eller tapt stille. I motsetning til pessimistisk låsing, låser den ikke enheter på databasenivå, og følgelig er den ikke sårbar for DB-lås.

Vi har lært at optimistisk låsing er aktivert for versjonerte enheter som standard. Det er imidlertid flere måter å be om det eksplisitt ved å bruke forskjellige typer låsemodus.

Et annet faktum vi bør huske er at hver gang det er motstridende oppdateringer av enheter, bør vi forvente en OptimisticLockException.

Til slutt er kildekoden til denne opplæringen tilgjengelig på GitHub.


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