Hvorfor det er behov for transaksjoner
Svært ofte, når du arbeider med en database, oppstår det en situasjon når du trenger å utføre mange forskjellige handlinger, men de gir bare mening sammen.
For eksempel skriver vi bankprogramvare som skal gjøre tre ting:
- Ta ut penger fra kundens konto
- Legg til penger på mottakerens konto
- Registrer postingsdataene i "posteringsloggen"
Hvis det oppstår en feil under utførelsen av noen av disse handlingene, må de to andre også kanselleres. Er det umulig å avskrive penger fra klienten og ikke legge dem til mottakeren? Vel, eller legge til mottakeren, men ikke avskrive fra klienten?
Så en slik logisk gruppering av forskjellige handlinger i én kalles en transaksjon . Med andre ord er en transaksjon en gruppe handlinger som bare må utføres samlet . Hvis en handling mislyktes eller ble utført med en feil, må alle andre handlinger kanselleres.
En transaksjon har vanligvis tre tilstander:
- initial state - tilstanden til systemet før en gruppe handlinger utføres
- suksesstilstand - tilstand etter at aksjonsgruppen er fullført
- mislykket tilstand - noe gikk galt
I dette tilfellet er det vanligvis tre kommandoer:
- start/start - utført før starten av den logiske gruppen av handlinger
- commit - utføres etter transaksjonshandlingsgruppen
- rollback - starter prosessen med å returnere systemet fra mislykket tilstand til initial tilstand
Det fungerer slik.
Først må du åpne en transaksjon - kall start()- eller start()- metoden . Å kalle denne metoden indikerer tilstanden til systemet som vi vil prøve å gå tilbake til hvis noe går galt.
Deretter utføres alle handlinger, som kombineres til en logisk gruppe - en transaksjon.
Deretter kalles commit ()- metoden . Oppfordringen markerer slutten på en logisk gruppe handlinger, og starter også vanligvis prosessen med å sette disse handlingene ut i livet.
Husk hvordan vi skrev noe i FileWriter: Først lagres alt vi skrev i minnet, og så når flush () -metoden kalles , blir alle dataene fra bufferen i minnet skrevet til disken. Denne flush() er transaksjonsbekreftelsen.
Vel, hvis det oppstod en feil under operasjonen av transaksjonen, må du starte prosessen med å gå tilbake til starttilstanden. Denne prosessen kalles rollback() , og metoden med samme navn er vanligvis ansvarlig for den.
Grovt sett er det 2 måter å fullføre en transaksjon på:
- FORBINDELSE – vi bekrefter alle endringer som er gjort
- ROLLBACK - rulle tilbake alle endringer som er gjort
Transaksjoner i JDBC
Nesten alle DBMS kan jobbe med transaksjoner. Så JDBC har også støtte for denne saken. Alt er implementert veldig enkelt.
Først blir hvert kall til execute () -metoden til Statement-objektet utført i en separat transaksjon. For å gjøre dette har Connection en AutoCommit- parameter . Hvis den er satt til true , vil commit() bli kalt etter hvert kall til execute()- metoden .
For det andre, hvis du vil utføre flere kommandoer i en transaksjon, kan du gjøre det slik:
- deaktiver AutoCommit
- kaller våre kommandoer
- kall commit()- metoden eksplisitt
Det ser veldig enkelt ut:
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
connection.commit();
Hvis det oppstår en feil på serveren mens commit() -metoden kjører , vil SQL-serveren avbryte alle tre handlingene.
Men det er situasjoner når feilen fortsatt oppstår på klientsiden, og vi kom aldri til commit() -metodekallet :
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");
connection.commit();
Hvis det oppstår en feil under kjøringen av en executeUpdate() , vil ikke commit()- metoden bli kalt. For å rulle tilbake alle handlinger som er utført, må du kalle opp rollback() -metoden . Det ser vanligvis slik ut:
try{
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");
connection.commit();
}
catch (Exception e) {
connection.rollback();
}
Lagre punkter
Med bruken av JDBC 3.0 ble det mulig å jobbe mer effektivt med tilbakeføring av transaksjoner. Nå kan du angi lagre poeng - lagre poeng, og når du kaller tilbakerulling () operasjonen , rulle tilbake til et spesifikt lagre punkt.
For å lagre må du opprette et lagringspunkt, dette gjøres med kommandoen:
Savepoint save = connection.setSavepoint();
Å gå tilbake til et lagringspunkt gjøres med kommandoen:
connection.rollback(save);
La oss prøve å legge til et lagringspunkt før vår problematiske kommando:
try{
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE employee SET salary = salary+1000");
Savepoint save = connection.setSavepoint();
try{
int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");
}
catch (Exception e) {
connection.rollback(save);
}
connection.commit();
}
catch (Exception e) {
connection.rollback();
}
Vi organiserte nestede transaksjoner ved å legge til et lagringspunkt før vi kaller den problematiske metoden, og returnerer til den lagrede tilstanden ved å kalle tilbakerulling(lagre) -metoden .
Ja, det er veldig likt å lagre/laste i spill.
GO TO FULL VERSION