18.2.5 | Ausführen von SQL |
Wenn eine Verbindung zur Datenbank hergestellt wurde, kann man darüber SQL-Anweisungen ausführen. Im hier beschriebenen Beispiel wird »dynamisches SQL« für die Abfrage benutzt.
Zum Ausführen einer SQL-Anweisung mit dynamischem SQL wird zunächst ein Exemplar der Klasse Statement erzeugt:Connection con; // ... Statement stmt = con.createStatement();Durch Aufruf der Methode createStatement() eines Connection-Exemplars wird ein Statement-Exemplar zurückgeliefert. Dieses Exemplar kann man anschließend zur Ausführung von SQL-Anweisungen benutzen. Hierbei muss man zwischen SQL-Operationen unterscheiden, die Ergebnisse zurückliefern (Abfragen), und SQL-Anweisungen, die keine Ergebnisse zurückliefern (DML-Operationen). Diese zwei Kategorien von Anweisungen werden in den folgenden Abschnitten behandelt. Alle Beispiele dieses Abschnitts verwenden dynamisches SQL.
Abfragen sind SQL-Anweisungen, die ein Ergebnis zurückliefern. Sie werden in Java mit der Methode executeQuery() ausgeführt, wie folgendes Beispiel zeigt:Connection con; // ... Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM titel");executeQuery() ist im Interface Statement definiert und erwartet als Argument eine gültige SQL-Anweisung. Die übergebene SQL-Anweisung muss der Syntax des verwendeten Datenbanksystems entsprechen. Beim Aufruf wird der SQL-String zunächst an den JDBC-Treiber übergeben, der die Anweisung wiederum an das Datenbanksystem weiterreicht.
Als Ergebnis liefert executeQuery schließlich ein ResultSet-Exemplar zurück. Über das Interface ResultSet kann die Java-Anwendung auf das Ergebnis der Datenbankabfrage zugreifen. Ein ResultSet repräsentiert in Java einen Datenbank-Cursor.
Eine Ergebnisabfrage in JDBC sieht in der Praxis z. B. folgendermaßen aus:while(rs.next()) { System.out.println(rs.getString("titel")); }Über die Methode next() kann man das ResultSet-Exemplar auf den nächsten Datensatz positionieren. next() liefert einen booleschen Wert zurück, der anzeigt, ob ein weiterer Datensatz in der Ergebnismenge enthalten ist. In einer while-Schleife wird solange next() aufgerufen, bis das ResultSet keine Datensätze mehr zurückliefert. next() ergibt dann false. Liefert die Abfrage überhaupt keinen Satz zurück, ergibt bereits der erste Aufruf von next() false, und es wird überhaupt nicht in die while-Schleife verzweigt. Für jeden gefundenen Datensatz wird der Titelname auf der Standard-Ausgabe ausgegeben. Die Abfrage der Werte erfolgt über die Methode getString(). Als Parameter wird der Name der Spalte in der Datenbank übergeben, die in der Abfrage selektiert wurde. Eine detaillierte Beschreibung der Klasse ResultSet folgt in Abschnitt 18.6.
Nachdem die Verarbeitung der SQL-Anweisungen abgeschlossen ist, sollten die zuvor belegten Ressourcen wieder freigegeben werden. Hierzu gehören:Alle diese Klassen definieren die Methode close(), bei deren Aufruf die jeweils assoziierte Ressource freigegeben wird. Nach dem Schließen eines Datenbank-Objekts ist das Objekt nicht mehr aktiv und kann nicht mehr für die Kommunikation mit der Datenbank benutzt werden. Die Freigabe der Ressourcen erfolgt bei der Beispielanwendung am Ende durch folgenden Aufruf:
- Cursor, die durch Abfragen angelegt wurden (repräsentiert durch die Klasse ResultSet).
- Objekte zur Ausführung von SQL-Code (Statement für dynamisches SQL, PreparedStatement für vorbereitetes SQL und CallableStatement für Stored Procedures/Functions).
- Verbindungen zur Datenbank (repräsentiert durch die Klasse Connection).
// Verbindung schließen con.close();Es wird nur das Connection-Exemplar geschlossen, nicht jedoch das Statement und der ResultSet. Das ist ausreichend, da in JDBC die Ressourcen-Freigabe automatisch kaskadierend durchgeführt wird.Wenn man die Methode close() des Connection-Exemplars aufruft, werden automatisch die innerhalb der Verbindung erzeugten Datenbank-Objekte mit geschlossen. Analog dazu wird z. B. beim Schließen des Statement-Exemplars der aktuelle ResultSet geschlossen.
Im obigen Beispiel werden zwar weder DML- noch DDL-Anweisungen benutzt, aufgrund der Wichtigkeit wird jedoch bereits in diesem einführenden Abschnitt ein kurzes Beispiel für die Ausführung von DML- und DDL-Anweisungen gegeben. Die Verwendung von DML- und DDL-Operationen ist in JDBC noch einfacher als Abfragen, da bei der Ausführung keine Ergebnismenge zurückgeliefert wird. Als Rückgabewert erhält man lediglich eine Zahl, die angibt, wieviele Zeilen in der Datenbank verändert wurden. DML- und DDL-Anweisungen werden nicht mit executeQuery() ausgeführt, sondern mit einer anderen Methode: executeUpdate(). executeUpdate() erwartet als Argument eine gültige DML- oder DDL-Anfrage.
Folgender Code zeigt die Ausführung einer einfachen DML-Anweisung mit JDBC:Connection con; ... Statement stmt = con.createStatement(); String sql = "UPDATE titel SET preis = preis*0.9 WHERE vlg_id = 2"; int anzahl; anzahl = stmt.executeUpdate(sql); System.out.println("Es wurden "+anzahl+" Zeilen aktualisiert"); ... stmt.close();