Tot nog toe hebben we telkens een SQL-commando uitgevoerd, en deze werden ook onmiddellijk naar de databank doorgevoerd en uitgevoerd. De enige vertraging die we hadden was de vertering van de verbinding.
Maar wat als we gegevens behandelen die bij elkaar horen, en die van elkaar afhangen.
Neem bijvoorbeeld een bank applicatie waarbij wij een rekening bezitten en iemand anders ook. Wij willen geld overschrijven naar die andere persoon. Hierbij wordt een bepaald stappenplan doorlopen.
Elke stap in bovenstaand proces, is een andere query. Maar wat nu als het bijvoorbeeld fout gaat bij stap 3? Het geld is dan al van mijn rekening, maar de rekening van de tegenpartij bestaat helemaal niet. Wat nu?
Hier komen Transacties helpen. Deze zullen deze verschillende queries bundelen bij elkaar. En ons de mogelijkheid bieden om, indien er iets fout gaat, de volledige transactie, alle queries dus, terug te draaien. Zo komt het geld terug op mijn rekening en kan ik opnieuw proberen, deze keer met het juiste rekening nummer.
Om transacties te kunnen gebruiken moeten we deze eerst opstarten. Dat gebeurt met de methode setAutoCommit() van de Interface Connection. Hieraan geven we het argument false mee. Zo zullen de executes niet meer automatisch gecommit worden in de databank maar wachten tot de wij in de software deze opdracht geven.
Vanaf nu kunnen wij verschillende executes toevoegen en deze zullen tijdelijk worden uitgevoerd. Bekijk het alsof dit werkt in een kopij van de databank.
Om de executes ook daadwerkelijk uit te voeren gebruiken we de methode commit() van de Interface Connection. Deze zal dan alle queries uitvoeren in 1 keer.
Indien eer onderweg, of zelf nog op het einde, een probleem plaatsvindt, komen we in het catch block terecht van onze code. Er zijn dan ook verscheidene lijnen overgeslagen, alsook willen we dat de commando’s die al waren uitgevoerd, terug gedraaid worden.
Dit noemen we en RollBack. We kunnen, om dit te doen, de methode rollback() gebruiken van de interface Connection, om de commando’s terug te draaien die al uitgevoerd waren in de kopij van de databank. dit terug draaien wordt uitgevoerd tot de laatste commit die is uitgevoerd. Dit kan dus de oproep zijn om de transactie te starten (setAutoCommit(false)) of de laatste commit zijn.
Er is ook een manier om SavePoints in te voeren. Hiervoor verwijzen we graag naar de uitgebreide API Documentatie van de Interface Connection.
In de code komt dit er dan zo bijvoorbeeld uit te zien.
try (
Connection connect = DriverManager.getConnection(url, login, psw);
) {
try (
Statement statement = connect.createStatement();
) {
connect.setAutoCommit(false); // start transactie
statement.executeUpdate(SQL1);
statement.executeUpdate(SQL2);
connect.commit(); // Commit transactie
} catch(SQLException sqle) {
connect.rollback();
}
}
Let hier op dat de autoCommit nog steeds op false staat. Na de commit is er dus nog steeds een transactie aanwezig, deze bevat alleen nog geen nieuwe commando’s. Indien je deze wilt sluiten kan dat via de connect.setAutoCommit(true). Zo zal terug elk SQL-commando automatisch worden uitgevoerd en gecommit naar de Databank.
Hieronder nog even een voorbeeld met de JdbcFacade.
try (
JdbcFacade jdbcHelper = new JdbcFacade();
) {
jdbcHelper.startTransaction();
statement.executeUpdate(SQL1);
statement.executeUpdate(SQL2);
jdbcHelper.stopTransaction();
} catch(SQLException sqle) {
jdbcHelper.rollback();
}
Methode | Omschrijving |
setAutoCommit(false) | Schakelt transacties in |
executeUpdate()executeQuery() | SQL-Commando’s worden opgestapeld (stack) |
setSavePoint() | Stelt een savepoint in |
rollback() | Opgestapelde commando’s worden geannuleerd |
commit() | Opgestapelde commando’s worden als geheel definitief gemaakt |
setAutoCommit(true) | Schakelt transacties opnieuw uit |