From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100267.html | 633 +++++++++++++++++++++ 1 file changed, 633 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100267.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100267.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100267.html b/Master/Reference Architectures and Patterns/hjp5/html/k100267.html new file mode 100644 index 0000000..ebab778 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100267.html @@ -0,0 +1,633 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 42 - Datenbankzugriffe mit JDBC +
+
+ + + + +

42.2 Grundlagen von JDBC

+
+ +
+ + + + +

42.2.1 Öffnen einer Verbindung

+ +

+Bevor mit JDBC auf eine Datenbank zugegriffen werden kann, muss zunächst +eine Verbindung zu ihr hergestellt werden. Dazu muss der Datenbanktreiber +geladen und initialisiert und mit Hilfe des Treibermanagers ein Verbindungsobjekt +beschafft werden. Es bleibt während der gesamten Verbindung bestehen +und dient als Lieferant für spezielle Objekte zur Abfrage und +Veränderung der Datenbank. Alle Klassen zum Zugriff auf die JDBC-Schnittstelle +liegen im Paket java.sql, +das am Anfang des Programms importiert werden sollte: +

+ + + + +
+ +
+import java.sql.*;
+
+
+
+ +

+Jeder JDBC-Treiber hat einen statischen Initialisierer, der beim Laden +der Klasse aufgerufen wird. Seine Aufgabe besteht darin, sich beim +Treibermanager zu registrieren, um +bei späteren Verbindungsanfragen von diesem angesprochen werden +zu können. Das Laden der Treiberklasse wird üblicherweise +durch Aufruf der Methode forName +der Klasse Class +erledigt (siehe Abschnitt 43.2.2). +Um einen Treiber zu laden, muss man also seinen vollständigen +Klassennamen kennen: + +

+Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
+
+ + +

+sun.jdbc.odbc.JdbcOdbcDriver +ist der Name der JDBC-ODBC-Bridge, mit der die oben erwähnten +Typ-1-Treiber realisiert werden. Die Namen alternativer Treiber sind +der Dokumentation des jeweiligen Herstellers zu entnehmen. + +

+Nachdem der Treiber geladen wurde, kann er dazu verwendet werden, +eine Verbindung zu einer Datenbank aufzubauen. Dazu wird an die statische +Methode getConnection +der Klasse DriverManager +ein String und eventuell weitere Parameter übergeben, um den +Treibertyp, die Datenbank und nötigenfalls weitere Informationen +festzulegen. getConnection +gibt es in drei Ausprägungen: +

+ + + + + +
+ +
+static Connection getConnection(
+  String url
+)
+
+static Connection getConnection(
+  String url,
+  String user,
+  String password
+)
+
+static Connection getConnection(
+  String url,
+  Properties info
+)
+
+
+
+java.sql.DriverManager
+ +

+Die erste Variante erwartet lediglich einen Connection-String als +Argument, der in Form eines URL (Uniform Ressource Locator, siehe +Abschnitt 40.1.1) übergeben +wird. Der Connection-String besteht aus mehreren Teilen, die durch +Doppelpunkte voneinander getrennt sind. Der erste Teil ist immer »jdbc« +und zeigt an, dass es sich um einen JDBC-URL handelt. Der zweite Teil +wird als Sub-Protokoll bezeichnet und gibt an, welcher Treiber +verwendet werden soll. Die übrigen Teile sind treiberspezifisch. +Connection-Strings für die JDBC-ODBC-Bridge beginnen immer mit +»jdbc:odbc«, gefolgt von einem weiteren Doppelpunkt, nach +dem der Name der ODBC-Datenquelle angegeben wird: + +

+con = DriverManager.getConnection("jdbc:odbc:DirDB");
+
+ + +

+Die zweite Variante von getConnection +erlaubt es, zusätzlich den Benutzernamen und das Passwort an +die Datenbank zu übergeben. Das ist bei vielen Datenbanken erforderlich, +um eine Verbindung aufbauen zu können. Bei der dritten Variante +können zusätzlich mit Hilfe eines Properties-Objekts +weitere, treiberspezifische Informationen übergeben werden. Welche +Variante zu verwenden ist, muss der jeweiligen Treiberdokumentation +entnommen werden. +

+ + + + + + + + + +
+ +

+Falls die Datenbank nicht geöffnet werden konnte, löst getConnection +eine Ausnahme des Typs SQLException +aus. Diese Ausnahme wird auch von fast allen anderen Methoden und +Klassen verwendet, um einen Fehler beim Zugriff auf die Datenbank +anzuzeigen.

+ + + + +
 Hinweis 
+
+ +

+Wenn die Verbindung erfolgreich aufgebaut werden konnte, liefert getConnection +ein Objekt, das das Interface Connection +implementiert. Dieses Verbindungsobjekt repräsentiert die aktuelle +Datenbanksitzung und dient dazu, Anweisungsobjekte zu erzeugen und +globale Einstellungen an der Datenbank zu verändern. Das Connection-Objekt +kann durch Aufruf von close +explizit geschlossen werden. Die Verbindung wird automatisch geschlossen, +wenn die Connection-Variable +vom Garbage Collector zerstört wird. + + + + +

42.2.2 Erzeugen von Anweisungsobjekten

+ +

+Alle Abfragen und Änderungen der Datenbank erfolgen mit Hilfe +von Anweisungsobjekten. Das sind Objekte, +die das Interface Statement +oder eines seiner Subinterfaces implementieren und von speziellen +Methoden des Connection-Objekts +erzeugt werden können: +

+ + + + + +
+ +
+Statement createStatement()
+
+PreparedStatement prepareStatement(String sql)
+
+CallableStatement prepareCall(String sql)
+
+
+
+java.sql.Connection
+ +

+Die einfachste Form ist dabei das von createStatement +erzeugte Statement-Objekt. +Es kann dazu verwendet werden, unparametrisierte Abfragen und Änderungen +der Datenbank zu erzeugen. Seine beiden wichtigsten Methoden sind +executeQuery +und executeUpdate. +Sie erwarten einen SQL-String als Argument und reichen diesen an die +Datenbank weiter. Zurückgegeben wird entweder ein einfacher numerischer +Ergebniswert, der den Erfolg der Anweisung anzeigt, oder eine Menge +von Datenbanksätzen, die das Ergebnis der Abfrage repräsentieren. +Auf die beiden übrigen Anweisungstypen werden wir später +zurückkommen. +

+ + + + + + + + + + + +
+ +

+Statement-Objekte +sind bei manchen Treibern kostspielige Ressourcen, deren Erzeugen +viel Speicher oder Rechenzeit kostet. Das Erzeugen einer großen +Anzahl von Statement-Objekten +(beispielsweise beim Durchlaufen einer Schleife) sollte in diesem +Fall vermieden werden. Viele JDBC-Programme legen daher nach dem Öffnen +der Verbindung eine Reihe von vordefinierten Statement-Objekten +an und verwenden diese immer wieder. Obwohl das im Prinzip problemlos +möglich ist, kann es in der Praxis leicht dazu führen, dass +ein Statement-Objekt, +das noch in Gebrauch ist (beispielsweise, weil seine Ergebnismenge +noch nicht vollständig abgefragt ist), erneut verwendet wird. +Das Verhalten des Programms ist dann natürlich undefiniert. Wir +werden später in Abschnitt 42.4.5 +eine Lösung für dieses Problem kennenlernen.

+ + + + +
 Warnung 
+
+ + + + +

42.2.3 Datenbankabfragen

+ +

+Hat man ein Statement-Objekt +beschafft, kann dessen Methode executeQuery +verwendet werden, um Daten aus der Datenbank zu lesen: +

+ + + + + +
+ +
+public ResultSet executeQuery(String sql)
+  throws SQLException
+
+
+
+java.sql.Statement
+ +

+Die Methode erwartet einen SQL-String in Form einer gültigen +SELECT-Anweisung und gibt ein Objekt +vom Typ ResultSet +zurück, das die Ergebnismenge repräsentiert. Als Argument +dürfen beliebige SELECT-Anweisungen übergeben werden, sofern +sie für die zugrunde liegende Datenbank gültig sind. Die +folgende SQL-Anweisung selektiert beispielsweise alle Sätze aus +der Tabelle dir, deren Feld +did den Wert 7 hat: + +

+SELECT * FROM dir WHERE did = 7
+
+ + +

+Das zurückgegebene Objekt vom Typ ResultSet +besitzt eine Methode next, +mit der die Ergebnismenge schrittweise durchlaufen werden kann: +

+ + + + + +
+ +
+boolean next()
+
+
+
+java.sql.ResultSet
+ +

+Nach dem Aufruf von executeQuery +steht der Satzzeiger zunächst vor dem ersten Element, +jeder Aufruf von next +positioniert ihn auf das nächste Element. Der Rückgabewert +gibt an, ob die Operation erfolgreich war. Ist er false, +gibt es keine weiteren Elemente in der Ergebnismenge. Ist er dagegen +true, +konnte das nächste Element erfolgreich ausgewählt werden, +und mit Hilfe verschiedener get...-Methoden +kann nun auf die einzelnen Spalten zugegriffen werden. Jede dieser +Methoden steht in zwei unterschiedlichen Varianten zur Verfügung: +

+ +

+Um dem Entwickler lästige Typkonvertierungen zu ersparen, gibt +es alle getXXX-Methoden in unterschiedlichen +Typisierungen. So liefert beispielsweise getString +das gewünschte Feld als String, +während getInt +es als int +zurückgibt. Wo es möglich und sinnvoll ist, werden automatische +Typkonvertierungen durchgeführt; getString +kann beispielsweise für nahezu alle Typen verwendet werden. Tabelle 42.1 +gibt eine Übersicht über die wichtigsten get-Methoden +der Klasse ResultSet. +In Tabelle 42.4 findet sich +eine Übersicht der wichtigsten SQL-Datentypen. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RückgabewertMethodenname
boolean +getBoolean
byte +getByte
byte[] +getBytes
Date +getDate
double +getDouble
float +getFloat
int +getInt
long +getLong
short +getShort
String +getString
Time +getTime
Timestamp +getTimestamp
+

+Tabelle 42.1: get-Methoden von ResultSet

+

+ + + + + + + + + +
+ +

+Soll festgestellt werden, ob eine Spalte den Wert NULL +hatte, so kann das nach dem Aufruf der get-Methode +durch Aufruf von wasNull +abgefragt werden. wasNull +gibt genau dann true +zurück, wenn die letzte abgefragte Spalte einen NULL-Wert +als Inhalt hatte. Bei allen Spalten, die NULL-Werte +enthalten können, muss diese Abfrage also erfolgen. Bei +den get-Methoden, die ein Objekt +als Ergebniswert haben, geht es etwas einfacher. Hier wird null +zurückgegeben, wenn der Spaltenwert NULL +war.

+ + + + +
 Hinweis 
+
+ + + + +

42.2.4 Datenbankänderungen

+ +

+Datenbankänderungen werden mit den SQL-Anweisungen INSERT INTO, +UPDATE +oder DELETE FROM +oder den SQL-DDL-Anweisungen (Data Definition Language) +zum Ändern der Datenbankstruktur durchgeführt. Im Gegensatz +zu Datenbankabfragen geben diese Anweisungen keine Ergebnismenge zurück, +sondern lediglich einen einzelnen Wert. Im Falle von INSERT INTO, +UPDATE +und DELETE FROM +gibt dieser Wert an, wie viele Datensätze von der Änderung +betroffen waren, bei DDL-Anweisungen ist er immer 0. + +

+Um solche Anweisungen durchzuführen, stellt das Interface Statement +die Methode executeUpdate +zur Verfügung: +

+ + + + + +
+ +
+public int executeUpdate(String sql)
+  throws SQLException
+
+
+
+java.sql.Statement
+ +

+Auch sie erwartet als Argument einen String mit einer gültigen +SQL-Anweisung, beispielsweise: + +

+INSERT INTO dir VALUES (1, 'x.txt', 0)
+
+ + +

+Könnte diese Anweisung erfolgreich ausgeführt werden, würde +sie 1 zurückgeben. Andernfalls würde eine SQLException +ausgelöst. + + + + +

42.2.5 Die Klasse SQLException

+ +

+Wenn SQL-Anweisungen fehlschlagen, lösen sie normalerweise eine +Ausnahme des Typs SQLException +aus. Das gilt sowohl, wenn keine Verbindung zur Datenbank zustande +gekommen ist, als auch bei allen Arten von Syntaxfehlern in SQL-Anweisungen. +Auch bei semantischen Fehlern durch falsche Typisierung oder inhaltlich +fehlerhafte SQL-Anweisungen wird eine solche Ausnahme ausgelöst. +SQLException +ist eine Erweiterung der Klasse Exception +und stellt folgende zusätzliche Methoden zur Verfügung: +

+ + + + + +
+ +
+int getErrorCode()
+
+String getSQLState()
+
+SQLException getNextException()
+
+
+
+java.sql.SQLException
+ +

+Mit getErrorCode +kann der herstellerspezifische Fehlercode abgefragt werden, getSQLState +liefert den internen SQL-Zustandscode. Etwas ungewöhnlich ist +die Methode getNextException, +denn sie unterstützt die Verkettung von Ausnahmen. Jeder +Aufruf holt die nächste Ausnahme aus der Liste. Ist der Rückgabewert +null, +gibt es keine weiteren Ausnahmen. Code zum Behandeln einer SQLException +könnte also etwa so aussehen: + + +

+ + + + +
+ +
+001 ...
+002 catch (SQLException e) {
+003   while (e != null) {
+004     System.err.println(e.toString());
+005     System.err.println("SQL-State: " + e.getSQLState());
+006     System.err.println("ErrorCode: " + e.getErrorCode());
+007     e = e.getNextException();
+008   }
+009 }
+
+
+ +Listing 42.1: Behandeln einer SQLException

+ + + + +

42.2.6 Die Klasse SQLWarning

+ +

+Neben der Klasse SQLException +für kritische Ausnahmen und Fehler enthält das Paket java.sql +auch die Klasse SQLWarning. +Diese wird allerdings nicht geworfen, sondern muss über die Methode +getWarnings abgerufen werden. +SQLWarning wird von den Klassen +Connection, Statement +und ResultSet unterstützt. + +

+Die Methode getWarnings liefert +Ihnen gegebenenfalls das erste SQLWarning-Objekt +zur Auswertung zurück. Sollten weitere Warnungen existieren erhalten +Sie diese über die Methode getNextWarning. +


+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3