Einfügen von Daten in eine
Tabelle
Um Daten in eine Tabelle einzufügen, wird ein Statement-Objekt benötigt, das über ein Connection-Objekt erzeugt wird.
java.sql.Statement stmt = conn.createStatment();
Mit folgendem Code wird ein SQL-Befehl an die Datenbank gesendet und ein Satz in die Tabelle VEHICLE eingefügt.
try {
stmt.executeUpdate ("insert into VEHICLE "
+ "(NAME, PRICE, CURRENCY)"
+ "values ('Audi80', 25000, 'EUR')");
} finally {
stmt.close();
}
Mit derselben Methode können auch UPDATE oder DELETE SQL-Befehle an die Datenbank gesendet werden und dadurch Sätze geändert und gelöscht werden. Es ist notwendig, ein nicht mehr benötigtes Statement-Objekt mittels seiner close()-Methode zu schließen. Am sichersten geschieht dies durch einen finally Block.
Eine effizientere Methode zum Einfügen von Sätzen besteht in der Verwendung von PreparedStatement-Objekten. Das PreparedStatement interface erweitert das interface Statement, und bietet folgende Vorteile:
· Beim Anlegen von PreparedStatement-Objekten wird der enthaltene SQL-Befehl zur Datenbank gesendet und dort nur übersetzt. Innerhalb der executeUpdate-Methode ist dann im Unterschied zu Statement-Objekten keine Übersetzung mehr notwendig. Die Übersetzung von SQL-Befehlen durch die Datenbank ist in der Regel eine aufwendige Operation.
· PreparedStatement-Objekte werden gepuffert (Statement Pooling)
· PreparedStatement-Objekte können Eingabeparameter für Spaltenwerte entgegennehmen.
In unserem Beispiel würde derselbe Datensatz wie folgt eingefügt.
java.sql.PreparedStatement ps =
con.prepareStatement("insert into VEHICLE " +
"(NAME, PRICE, CURRENCY) " +
"values (?, ?, ?)");
Die Fragezeichen sind Platzhalter für konkrete Werte, die vor der Ausführung eines SQL-Befehls gesetzt werden müssen. Die Platzhalter werden mit den setXXX-Methoden von PreparedStatement gefüllt und beginnend mit 1 durchnummeriert.
try {
ps.setString (1, "Audi80");
ps.setInt(2, 25000);
ps.setString(3, "EUR");
ps.executeUpdate();
} finally {
ps.close();
}
Welche setXXX-Methoden für welche Datentypen zulässig sind, ist der Typkompatibiltätsmatrix zu entnehmen. Ein PreparedStatement-Objekt muss keine Eingabeparameter besitzen, es ist aber dann besonders nützlich, wenn sich in einem SQL-Befehl nur die Werte derselben Spalten ändern.
Die effizienteste Weise, um mehrere Datensätze in eine Datenbank einzufügen, besteht in der Verwendung der sogenannten Batch-Methoden von PreparedStatement.
PreparedStatement ps =
con.prepareStatement("insert into VEHICLE " +
"(NAME, PRICE, CURRENCY) " +
"values (?, ?, ?)");
try {
ps.setString (1, "VW Polo");
ps.setInt(2, 15000);
ps.setString(3, "EUR");
ps.addBatch();
ps.setString (1, "BMW 323");
ps.setInt(2, 30000);
ps.setString(3, "EUR");
ps.addBatch();
...
ps.executeBatch();
} finally {
ps.close();
}
Die einzelnen Änderungsoperationen werden im JDBC-Treiber aufgesammelt und dann im Paket an die Datenbank gesendet. Um addBatch-Operationen zu anullieren, steht dem JDBC-Programmierer die Methode clearBatch zur Verfügung. Es ist notwendig, ein nicht mehr benötigtes PreparedStatement-Objekt mittels seiner close()-Methode zu schließen. Am sichersten geschieht dies durch einen finally Block.
Können nicht alle Sätze eingefügt werden, wird eine BatchUpdateException geworfen. In diesem Fall muss ein Open JDBC-Programmierer mit einem der folgenden beiden Verhalten rechnen.
...
1. Die nicht eingefügten Sätze werden in einem Ausgabearray (s.u.) vermerkt.
2. Es werden nur die ersten n Sätze eingefügt, die Zahl n kann ermittelt werden.
Ein typisches Fehlerbehandlungsszenario sieht also wie folgt aus.
import java.sql.BatchUpdateException;
import java.sql.PreparedStatement;
...
int expectedInsCnt = 0;
ps.setString (1, "VW Polo");
ps.setInt(2, 15000);
ps.setString(3, "EUR");
ps.addBatch();
expectedInsCnt ++;
ps.setString (1, "BMW 323");
ps.setInt(2, 30000);
ps.setString(3, "EUR");
ps.addBatch();
expectedInsCnt ++;
try {
ps.executeBatch();
}
catch (BatchUpdateException bue) {
int[] insCnts = bue.getUpdateCounts();
int insCntSize = isnCnts.length;
if ( insCntSize == expectedInsCnt ) {
/* Fall 1 */
for (int i = 0; i < insCntSize; i++) {
if ( insCnts[i] == -3 ) {
// Satz i+1 konnte nicht eingefügt werden
}
}
} else if (insCntSize < expectedInsCnt) {
/* Fall 2: die ersten insCntSize Sätze wurden
eingefügt */
}
} finally {
ps.close();
}
Wichtig ist also die Methode BatchUpdateException.getUpdateCounts(), welche die fehlerhaften bzw. erfolgreich eingefügten Sätze identifiziert.