Eine Stapeloperation (Batch Update) beinhaltet eine Menge von Anweisungen (Statements), die zur Aktualisierung an eine Datenbank gesendet werden, um sie anschließend sukzessive in Form eines Stapels abzuarbeiten. Bei der Manipulation großer Mengen von Datensätzen muss für jede Operation (bspw. INSERT, DELETE oder UPDATE) ein neues Statement-Objekt oder eine der erweiterten Klassen (PreparedStatement bzw. CollableStatement) ausgeführt werden. Diese Vorgehensweise des JDBC in der Version 1.0 hat sich jedoch als langsam erwiesen, da jedes Statement einzeln an das DBMS geschickt wird und die Antwort abgewartet werden muss, bevor das nächste Element verarbeitet werden kann. Die JDBC-Version 2.0 löst dieses Problem, indem mehrere, zum Teil heterogene Anweisungen zusammengefasst und als Einheit zum DBMS gesendet werden. Diese Fähigkeit, eine zusammengesetzte Anweisungseinheit auf einmal zum DBMS zu schicken, wird als Stapeloperation (Batch Update) bezeichnet. Die Vorgehensweise bei der Erzeugung einer Stapeloperation ähnelt der Erzeugung von Statements jeglicher Art (Statement, PreparedStatement oder CollableStatement) mit dem Unterschied, dass die Anweisungen nicht direkt mit der Methode executeUpdate() ausgeführt werden, sondern mit der Methode addBatch() mittels der folgenden Syntax zu einer Operationsliste hinzugefügt werden: mein_stmnt.addBatch("Auszuführende Anweisung"); Eine Batch-Update-Anweisung wird erst ausgeführt, nachdem die Methode executeBatch() aufgerufen worden ist. mein_stmnt.executeBatch(); Im Folgenden wird nochmals auf die Tabelle Spieler eingegangen. Nun werden Daten anhand einer Stapeloperation aktualisiert, indem die Batch-Update-Vorgehensweise auf eine Instanz der Statement-Klasse angewendet wird: con.setAutoCommit(false); Statement mein_stmnt = mein_con.createStatement(); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(5, 'Joe', 'matson', 0)"); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(6, 'Jannet', 'jacks', 1)"); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(7, 'Alex', 'Groß', 1)"); int [] zaehleUpdate = mein_stmnt.executeBatch(); Im Folgenden wird der oben aufgeführte Code erläutert. Zuerst wird das automatische Senden der Transaktion an die Datenbank mit Hilfe der folgenden Zeile unterdrückt: con.setAutoCommit(false); Dieses Vorgehen ist bei der Verwendung von Stapeloperationen obligatorisch, damit eventuell auftretende Fehler geeignet behandelt werden können. Die folgende Zeile erzeugt eine Instanz der Statement-Klasse. Statement mein_stmnt = mein_con.createStatement(); Zu dieser Instanz werden mehrere Anweisungen hinzugefügt, um neue Werte in die Tabelle einsetzen zu können. Diese Anweisungen fügen drei neue Spieler in die Tabelle ein, wozu die folgenden Zeilen notwendig sind: mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(5, 'Joe', 'matson', 0)"); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(6, 'Jannet', 'jacks', 1)"); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(7, 'Alex', 'Groß', 1)"); Die letzte Zeile sendet die drei oben aufgezählten SQL-Anweisungen als Einheit an das DBMS. Der Grund für die Verwendung der Methode executeBatch() anstelle der Methode executeUpdate() liegt darin, dass executeUpdate() nur jeweils eine Anweisung senden kann. int [] zaehleUpdate = mein_stmnt.executeBatch(); Mit der letzten Zeile führt das DBMS die Kommandos sukzessive in der Reihenfolge aus, wie sie in der Liste angegeben sind. Somit wird zuerst der Spieler „Joe" in die Tabelle eingesetzt, gefolgt von „Jannet" und „Alex". Wenn die Aktualisierung der Daten erfolgreich abgeschlossen ist, besteht die Liste zaehleUpdate vom Typ int aus vier Elementen. Jedes dieser Element hat den Wert „1", da jedes Statement der Tabelle eine Zeile hinzugefügt hat. Analog zur Verwendung der Methode executeBatch() existiert die Methode clearBatch(), die veranlasst, dass die Liste auszuführender Anweisungen geleert wird. Abschließend sei der Leser darauf aufmerksam gemacht, dass nur Anweisungen, die eine Aktualisierungszahl (zaehleUpdate) zurückliefern, mit der Stapeloperationsmethode executeBatch() ausgeführt werden können. Zu diesen SQL-Anweisungen gehören unter anderem die SQL-Kommandos INSERT, UPDATE, DELETE, CREATE TABLE, DROP TABLE und auch ALTER TABLE. Exceptions in Stapeloperationen Zwei mögliche Exception-Arten können während einer Stapeloperation auftreten: SQLException und deren Erweiterung BatchUpdateException. Ein SQLException-Objekt wird von jeder Methode des JDBC-APIs erzeugt, wenn ein Fehler beim Zugriff auf die Datenbank aufgetreten ist. Wenn eine Anweisung durch die Stapeloperation nicht ausgeführt werden kann, wird ein BatchUpdateException-Objekt ausgeworfen. Zusätzlich zu den Informationen, die jedes Exception-Objekt mit sich trägt, beinhaltet ein BatchUpdateException-Objekt eine Liste (Datentyp Array) der Anweisungen, die korrekt ausgeführt wurden, bevor der Fehler aufgetreten ist. Dies ist unter anderem deshalb möglich, da eine Stapeloperation die Anweisungen in der Reihenfolge, in der sie angegeben wurden, ausführt. Der folgende Code erzeugt die SQL-Exceptions und die Ausnahmen bei der Berechnung der Aktualisierungszahl, die bei einer Stapeloperation entstehen können. Hierbei sollte beachtet werden, dass die BatchUpdateException-Klasse Ausnahmen der SQLException-Klasse auswerfen kann, da sie eine Erweiterung der Klasse SQLException darstellt. Da die Methode getUpdateCounts einen Array des Datentyps int zurückliefert, wird sie in einer for-Schleife abgearbeitet, um alle Werte ausgegeben zu können. try{ con.setAutoCommit(false); Statement mein_stmnt = mein_con.createStatement(); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(5, 'Joe', 'matson', 0)"); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(6, 'Jannet', 'jacks', 1)"); mein_stmnt.addBatch("INSERT INTO Spieler" + " VALUES(7, 'Alex', 'Groß', 1)"); int [] zaehleUpdate = mein_stmnt.executeBatch(); } catch(BatchUpdateException bue) { System.err.println("SQLException: " + bue.getMessage()); System.err.println("SQLState: " + bue.getSQLState()); System.err.println("Message: " + bue.getMessage()); System.err.println("ErrorCode: " + bue.getErrorCode()); System.err.print("Update counts: "); int [] zaehleUpdate = bue.getUpdateCounts(); for (int i = 0; i < zaehleUpdate.length; i++) { System.err.print(zaehleUpdate[i] + " "); } }