© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Java: Kapitel 8
Datenbankzugriff mit JDBC
Programmentwicklung WS 2008/2009
Holger Röder
holger.roeder@informatik.uni-stuttgart.de
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Überblick über Kapitel 8
Einführung in SQL und JDBC
Verbindung zur Datenbank
Einfache SQL-Anweisungen
Datenbankabfragen
Datenbankänderungen
Weiterführende Themen
Prepared Statements
SQL-Ausnahmen
Transaktionen
Java DB
2
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Structured Query Language (SQL)
SQL ist eine weit verbreitete Datenbanksprache zur Erzeugung,
Änderung und Abfrage von Daten in relationalen Datenbanken.
Beispiel: Tabelle erzeugen
CREATE TABLE person (vorname VARCHAR(30),
nachname VARCHAR(30), alterJahre INTEGER)
vorname
nachname alterJahre
Leonie
Lehmann
22
Gustav
Graf
46
Einfügen in die Datenbank
INSERT INTO person (vorname, nachname, alterJahre)
VALUES ('Leonie', 'Lehmann', 22)
INSERT INTO person VALUES ('Gustav', 'Graf', 46)
Abfrage
SELECT * FROM person WHERE alterJahre < 30
liefert 1 Eintrag
3
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Java Database Connectivity (JDBC)
Seit Java 1.1 existiert mit Java Database Connectivity (JDBC) eine
einheitliche Datenbankschnittstelle für Java-Programme.
JDBC ist eine Schnittstelle zwischen der (in aller Regel relationalen)
Datenbank und der Anwendung, die auf sie zugreifen will.
JDBC stellt ein Call Level Interface dar:
SQL-Befehle werden in der Anwendung als normale
Zeichenketten behandelt und als Parameter spezieller Methoden
an die Datenbank übermittelt.
Die Rückgabewerte der Methoden (Daten, Statuscodes) werden
dann von der Anwendung ausgewertet und weiterverarbeitet.
4
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
JDBC-Treiber
Der jeweilige JDBC-Treiber ist datenbankspezifisch. Für alle relevanten
SQL-Datenbanken stehen JDBC-Treiber zur Verfügung.
gleiche
JavaProgrammierAnwendung
schnittstelle
MySQL JDBCTreiber
MySQL-Datenbank
Oracle JDBCTreiber
Oracle-Datenbank
Die passende JDBC-Treiberbibliothek muss
(typischerweise als .jar-Archiv) im
Klassenpfad (classpath) vorhanden sein.
Das Paket java.sql enthält die
JDK-Klassen für den JDBC-Zugriff.
5
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
JDBC-Treiber laden
Bis einschließlich Java 5 muss vor dem Verbindungsaufbau der zur
Datenbank passende JDBC-Treiber geladen werden. Dies kann über die
Klasse Class erfolgen.
Klassenname
MySQL:
muss bekannt
Class.forName("com.mysql.jdbc.Driver");
sein.
Apache Derby/Java DB (Embedded Mode):
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Oracle 8i:
Class.forName("oracle.jdbc.driver.OracleDriver");
Ab Java 6 (mit JDBC 4.0) entfällt das explizite Laden des JDBCTreibers. Beim ersten Verbindungsaufbau zur Datenbank wird der
Treiber automatisch gesucht und geladen.
6
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Verbindungsaufbau zur Datenbank
Mit der statischen Methode getConnection() der Klasse
DriverManager kann eine Verbindung zur Datenbank hergestellt
werden:
Connection c = DriverManager.getConnection("jdbc:derby:TestDB");
...
c.close(); // Verbindung schließen
Connection-String
Connection-Objekt repräsentiert
die Verbindung zur DB
Connection-String: "jdbc:Treiber:DB-spezifische Teile"
Variante von getConnection() mit Angabe von Benutzername und
Passwort:
Connection c = DriverManager.getConnection(
"jdbc:oracle:oci:@OracleTest", "user", "password");
Connection-String
für Oracle-Datenbank
7
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Einfache SQL-Abfragen
Abfragen und Änderungen der Datenbank erfolge über StatementObjekte (Objekte, die die Schnittstelle Statement implementieren).
createStatement() liefert ein einfaches, nicht parametrisierbares
Statement-Objekt zurück.
SQL-Abfragen (SELECT) können über executeQuery() ausgeführt
werden und liefern ein ResultSet-Objekt mit dem Ergebnis zurück.
... // ggf. JDBC-Treiber laden, Connection-Objekt c holen
Statement s = c.createStatement();
Statement-Objekt holen
String sql = "SELECT vorname, name, id " +
"FROM mitarbeiter " +
SQL-Abfrage ausführen
"WHERE vorname = 'Carla'";
ResultSet result = s.executeQuery(sql);
Über Ergebnis iterieren
while (result.next()) {
String vorname = result.getString(1);
getXXX(spalte)
String nachname = result.getString(2);
liefert entsprechenden
Spaltenwert
int id = result.getInt(3);
System.out.format("%s %s (id=%d)%n", vorname, nachname, id);
}
result.close(); // Result-Objekt schließen
8
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Einfache SQL-Änderungen
Änderungen an der Datenbank (INSERT, DELETE, UPDATE) werden
über die Methode executeUpdate() durchgeführt.
...
String sql1 = "DELETE " +
"FROM mitarbeiter " +
"WHERE vorname = 'Carla'";
int result1 = s.executeUpdate(sql1);
Änderung durchführen:
executeUpdate()
liefert als Rückgabewert
die Zahl der geänderten
Zeilen zurück.
String sql2 = "INSERT INTO mitarbeiter (vorname, nachname)" +
"VALUES ('Sarah', 'Schmidt')";
int result2 = s.executeUpdate(sql2);
String sql3 = "UPDATE mitarbeiter " +
"SET vorname='Sandra' " +
"WHERE vorname = 'Sarah' AND nachname = 'Schmidt'";
int result3 = s.executeUpdate(sql3);
...
s.close(); // Statement schließen
c.close(); // Verbindung schließen
9
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Prepared Statements
Parametrisierte SQL-Anweisungen werden Prepared Statements
Platzhalter ?
genannt.
Prepared Statements werden zunächst mit Platzhaltern definiert:
PreparedStatement p = c.prepareStatement(
"INSERT INTO ankunft (vorname, nachname, zeit) VALUES (?, ?, ?)");
Vor der Ausführung des Prepared Statements werden die Platzhalter
dann durch konkreten Werte ersetzt:
setXXX(n, wert) setzt konkreten
p.setString(1, "Emil");
Wert für n-ten Platzhalter
p.setString(2, "Erler");
p.setTime(3, new Time(Calendar.getInstance().getTimeInMillis()));
p.executeUpdate();
Vorteile von Prepared Statements
Übersichtlichkeit, Wiederverwendbarkeit, Sicherheit
Bequeme Angabe verschiedener Datenformate: setString(),
setInt(), setDate(), setBlob() etc.
Datenbank-Performance
10
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Ausnahmebehandlung
Tritt im Zusammenhang mit dem Datenbankzugriff ein Fehler auf, wird
eine Ausnahme vom Typ SQLException (oder einer Unterklasse)
geworfen.
Typische „Auslöser“ einer SQLException:
Keine Verbindung zur Datenbank möglich
Fehlerhafte SQL-Syntax
Methoden:
getErrorCode() – liefert den herstellerspezifischen Fehlercode
getSQLState() – liefert den SQL-Zustandscode
getNextException() – SQLExceptions können verkettet
werden; diese Methode liefert das nächste SQLException-Objekt
zurück (oder null)
try {
c = DriverManager.getConnection("jdbc:derby:TestDB");
} catch (SQLException e) {
System.err.println("Keine Verbindung zur Datenbank möglich");
System.err.println("Fehlercode: " + e.getErrorCode());
}
11
© Holger Röder
Winter 2008/2009
Transaktionen
Standardmäßig wird jede einzelne SQL-Anweisung als separate
Transaktion angesehen und sofort ausgeführt (Auto-Commit-Modus).
Häufig sollen jedoch mehrere aufeinander folgende Datenbankanweisungen zusammengefasst als eine Transaktion ausgeführt
werden („ganz oder gar nicht“).
Connection c = ...
Auto-Commit-Modus abschalten
c.setAutoCommit(false);
Statement s = c.createStatement();
Programmentwicklung
// Typisches Transaktionsbeispiel:
// Banküberweisung von Konto A nach Konto B
se
int kontostandA = kontostandA – 500;
int kontostandB = kontostandB + 500;
s.executeUpdate("UPDATE konto " +
"SET kontostand = " + kontostandA + " WHERE kontoname = 'A'");
s.executeUpdate("UPDATE konto " +
"SET kontostand = " + kontostandB + " WHERE kontoname = 'B'");
c.commit();
Transaktion "committen" (SQL-Anweisungen ausführen)
12
© Holger Röder
Winter 2008/2009
Java DB / Apache Derby
Java DB ist eine leichtgewichtige relationale Datenbank und
Bestandteil von Java 6.
Java DB ist die von Sun unterstützte Variante der Open-SourceSoftware Apache Derby.
Eigenschaften:
100% in Java implementiert
Geringer Speicherbedarf (.jar nur ~2 MB)
Embedded-Modus, direkte Einbettung in die Java-Applikation
Programmentwicklung
http://db.apache.org/derby
se
13
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Einbindung von Java DB in ein Java-Projekt
Einbindung der Derby-Bibliothek in ein Java-Projekt in Eclipse:
Menü Project Æ Properties Æ Abschnitt Java Build Path
Æ Button Add External JARs…
Bibliothek derby.jar im Pfad [derby-dir]/lib einbinden
Die Bibliothek derby.jar ist Teil des JDK; alternativ ist sie unter
http://db.apache.org/derby/derby_downloads.html verfügbar.
14
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Java DB und JDBC
Stammverzeichnis für
DB-Dateien setzen
System.setProperty("derby.system.home", "C:/pe/db");
// Java 5: Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection c = DriverManager.getConnection(
"jdbc:derby:TestDB;create=true");
create=true: DB wird erzeugt,
wenn sie noch nicht existiert
Statement s = c.createStatement();
// Tabelle person anlegen
s.executeUpdate("CREATE TABLE person " +
"(vorname VARCHAR(30), nachname VARCHAR(30)");
// Neuen Eintrag in Tabelle person einfügen
s.executeUpdate("INSERT INTO person (vorname, nachname)" +
"VALUES ('Sarah', 'Schmidt')");
c.close();
Die Derby-Datenbank wird implizit gestartet, wenn eine Verbindung
hergestellt wird. Die Datenbank wird im angegebenen Pfad gespeichert.
15