Folien zu JDBC

Werbung
JDBC
Literatur
Ausgewählte Implementierungsprobleme
Rebecca Tiarks
22. Januar 2009
1 / 50
JDBC
Literatur
Inhaltsverzeichnis
1
JDBC
2 / 50
JDBC
Literatur
Datenbanken
Sammeln, Zugreifen und Verwalten von Daten
in der Computerwelt geschieht das mit Datenbanken
Datenbank Management System (DBMS)
verschiedene Speicherformen: relationales Modell,
OO-Datenbanken, XML-Datenbanken
3 / 50
JDBC
Literatur
Datenbanken
relationale Datenbanken bestehen aus Tabellen mit Zeilen
(Tupel) und Spalten (Attribute)
Zeilen einer Relation Datenbankausprägung
Datenbankschema beschreibt die Struktur
viele verschiedene OpenSource und kommerzielle DBs
Oracle, MySQL, Microsoft Access ...
Zugriff auf Datenbank in Java mit JDBC
4 / 50
JDBC
Literatur
JDBC
Java Database Connectivity
Datenbankschnittstelle für Java
ist unabhängig von konkreten Datenbanksystemen
unterstützt alle wichtigen Merkmale die von einer relationalen
Datenbankschnittstelle erwartet werden
dynamisches SQL, vorbereitetes SQL, aktualisierbare Cursor,
vorwärtsscrollbare Cursor und weitere
5 / 50
JDBC
Literatur
Komponenten von JDBC
JDBC-API zum Datenbankzugriff für Anwendungsentwickler
um eine DB ansprechen können wird Treiber benötigt
JDBC-Treiber stellt die Implementierung der
JDBC-Schnittstelle für ein konkretes Datenbanksystem
der Treiber übernimmt die Kommunikation mit dem
Datenbanksystem
JDBC-Treibermanager verwaltet JDBC-Treiber innerhalb der
Java-Laufzeitumgebung
6 / 50
JDBC
Literatur
JDBC
JDBC-API legt fest durch welche Methodenaufrufe man aus
Java auf rel. Datenbanken zugreifen kann
Schnittstelle mit Java-Interfaces die im Paket java.sql
enthalten sind
Zugriffsmethoden für ein konkretes Datenbanksystem (Oracle,
MySQL) sind nicht enthalten
Zugriff wird von JDBC-Treibern durchgeführt
7 / 50
JDBC
Literatur
Klassen in JDBC
DriverManager wird benutzt um Verbindung zur DB
aufzubauen
Connection repräsentiert Verbindung wird benötigt für
SQL-Anweisungen und Zugriff auf Metadaten
Statement Basis-Klasse für SQL-Anweisungen
PreparedStatement vorbereitete Anweisung
ResultSet repräsentiert Ergebnis einer Anfrage
8 / 50
JDBC
Literatur
Vorgehen
Registrieren des JDBC-Treibers beim Treibermanager
Verbindungsaufbau zur DB
SQL-Anweisung erzeugen
Ausführen der SQL-Anweisung
Abfragen des Ergebnisses nach der Ausführung
Schließen der Datenbank Verbindung
9 / 50
JDBC
Literatur
JDBC-Treiber
Treiber implementieren die Funktionen der
JDBC-Schnittstellen aus java.sql
alle Datenbank spezifischen Zugriffsmethoden sind im Treiber
gekapselt
die Verwaltung des Treibers übernimmt der
JDBC-Treibermanager
will man eine Verbindung aufbauen registriert man den
Treiber beim Treibermanager
bei Verbindungsaufbau zur DB wird vom Treibermanager der
Treiber angefordert und initialisiert
10 / 50
JDBC
Literatur
Registrierung des Treibers
mehrere Möglichkeiten zur Registrierung des Treibers
Treiberklassen müssen sich im Klassenpfad befinden
statische Methode Class.forName()
erwartet vollqualifizierten Klassennamen des Treibers
Klasse wird gesucht, geladen und ins Laufzeit-System
eingebunden
String driver = " oracle . jdb . driver . OracleDriver " ;
Class . forName ( driver );
11 / 50
JDBC
Literatur
Registrierung des Treibers
weitere Möglichkeit Registrierung beim Aufruf des Interpreters
über die Option -D die Property jdbc.drivers übergeben
außerdem eine Liste von Klassennamen, die JDBC-Treiber
implementieren
Syntax:
java - Djdbc . drivers = < treiber1 >:..: < treiberN > < Klasse >
java - Djdbc . drivers = oracle . jdbc . driverOracleDriver < Klasse >
12 / 50
JDBC
Literatur
Verbindungs-URL
in JDBC wird Datenbankserver als URL angegeben
Syntax:
jdbc : < protokoll >: < subprotokoll >: < datenbank >
zuerst Schlüsselwort jdbc
Name des verwendeten Protokolls (darunter ist der Treiber
beim Treibermanager registriert)
alles nach dem Protokoll ist treiberspezifisch und wird nur
vom Treiber ausgewertet
String url = " jdbc : h2 : testdb " ;
13 / 50
JDBC
Literatur
Verbindungsaufbau
Verbindungsaufbau über den Treibermanager
Klasse DriverManager
definiert die Methode getConnection() mit jeweils
unterschiedlichen Parametern
als Rückgabe bekommt man ein Connection-Objekt zurück
String url = " jdbc : h2 : testdb " ;
Sting user = " sa " ;
String password = " " ;
Connection con ;
con = DriverManager . getConnection ( url , user , password );
14 / 50
JDBC
Literatur
Protokollierung
Treibermanager-API verfügt über integrierte
Protokollierungsfunktionen
hilfreich zur Fehlersuche
ist per Voreinstellung deaktiviert und muss explizit aktiviert
werden
Methode setLogWriter()
kann jederzeit wieder deaktiviert werden
PrintWriter logger ;
logger = new PrintWriter ( new OutputStreamWriter ( System . out ))
DriverManager . setLogWriter ( logger );
15 / 50
JDBC
Literatur
Datenbanksprache
dient zur Kommunikation zwischen Datenbanksystem und der
Anwendung bzw. Benutzer
Unterteilung in unterschiedliche Zwecke
Datenabfrage und Manipulation:
Data Manipulation Language (DML)
Verwaltung der DB und Definition der Datenstruktren:
Data Definition Language (DDL)
Berchitigungssteuerung:
Data Control Language (DCL)
16 / 50
JDBC
Literatur
Abfragen
Abfragen sind SQL-Operationen die ein Ergebnis zurückliefern
(SELECT)
in Java werden Anfragen mit der Methode executeQuery()
ausgeführt
Methode erwartet eine gültige SQL-Anweisung (muss der
Syntax des verwendeten Datenbanksystems entsprechen)
liefert ein ResultSet-Objekt zurück
das ReultSet repräsentiert einen Datenbank-Cursor
17 / 50
JDBC
Literatur
Freigabe von Ressourcen
belegte Ressourcen müssen wieder freigegeben werden
ResultSet, Statement und Connection verwenden große
Datenstrukturen (nicht auf garbage collector warten)
für alle Klassen existiert eine close() Methode
nach dem Schließen ist das Objekt nicht mehr aktiv und kann
nicht mehr verwendet werden
ausreichend das Connection-Objekt zu schließen da alle
innerhalb der Verbindung erzeugten Objekte mit geschlossen
werden
18 / 50
JDBC
Literatur
Verbindung beenden
eine Verbindung wird nach Gebrauch wieder gechlossen
sehr wichtig, deshalb sollte dies immer im finally-Block
geschehen
da Verbindung beendet wird und nicht der DriverManager
findet sich die Methode close() bem Connection-Objekt
try
{
con = DriverManager . getConnection (...);
}
catch ( SQLException e )
{
}
finally
{
if ( con != null )
try { con . close ();} catch ( SQLException e )
}
19 / 50
JDBC
Literatur
SQL-Typen vs. Java-Typen
bei Anweisungen müssen oft Parameter gesetzt werden oder
Werte abgefragt werden
Konvertierung zwischen Java-Typen und SQL-Typen
erforderlich
Type-Mapping mit JDBC 1.0 eingeführt bildet Java-Typen auf
SQL-Typen ab und umgekehrt
19 Typen für die in java.sql.Types eine Konstante definiert
ist die den Typ repräsentiert
bei der Abfrage von ResultSet-Werten können automatisch
Konvertierungen vorgenommen werden (durch
getXXX()-Methoden)
20 / 50
JDBC
Literatur
Dynamisches vs. Vorbereitetes SQL
zwei Möglichkeiten zum Ausführen von Anweisungen
dynamishes SQL und vorbereitetes SQL
beide setzen einen String in der Anwendung zusammen
wird bei Ausführung zum Server geschickt
Konstruktion kann zur Laufzeit durchgeführt werden
wenn Parameteranzahl variiert einfaches SQL
ansonsten vorbereitetes SQL (weniger Konvertierung, bessere
Performance)
21 / 50
JDBC
Literatur
Dynamisches SQL
komplette Anweisung wird als String zusammengestellt
wird anschließend an DBS geschickt
Paramter die in der Anweisung benutzt werden müssen von
Hand eingebaut werden
soll dieselbe Anweisung mit unterschiedlichen Parametern
ausgeführt werden muss String neu zusammengesetzt werden
Erzeugen eines Statement-Exemplares
Aufrufen der createStatement() Methode vom
Connection-Objekt aus
alle Anfragen, DDL und DDM Operationen werden über
Statement-Objekt durchgeführt
22 / 50
JDBC
Literatur
Abfragen und Operationen
Abfragen werden mit der Methode executeQuery()
durchgeführt
Methode erwartet eine gültige SELECT-Anweisung (muss der
Syntax des verwendeten Datenbanksystems entsprechen)
liefert ein ResultSet-Objekt zurück
executeUpdate() wird für DDL- und DDM-Operationen
verwendet
erwartet eine gültige INSERT, UPDATE, DELETE oder
CREATE Anweisung
String wird erst bei Ausführung dem Statement-Exemplar
übergeben
mit einem Exemplar können versch. Typen von Anweisungen
ausgeführt werden
23 / 50
JDBC
Literatur
Beispiel
String s = " SELECT * FROM test " ;
String u = " UPDATE test SET wert = 2 WHERE name = 1 " ;
Statement stmt = con . createStatement ();
...
ResultSet res = stmt . executeQuery ( s );
...
res . close ();
stmt . executeUpdate ( u );
...
stmt . close ();
24 / 50
JDBC
Literatur
Parameter
Parameter werden über String-Operationen eingebaut
Syntax des verwendeten DBS muss beachtet werden
relativ einfach bei Zeichenketten und Zahlenwerten da Syntax
standardisiert
schwieriger bei z.B. Datums-Typen
dynamische SQL-Anweisungen sind sehr allgemein definiert
eignen sich wenn die Anzahl der Parameter variieren kann z.B.
Suchanfrage
25 / 50
JDBC
Literatur
Parameter
String kriterien [];
Connection con ;
Statement stmt = con . createStatement ();
String s = " SELECT * FROM titel WHERE " ;
s += " titel LIKE ’" + kriterien [0]+ " ’" ;
for ( int i = 1; i < kriterien . length ; i ++){
s += " AND titel LIKE ’" + kriterien [ i ]+ " ’" ;
}
26 / 50
JDBC
Literatur
Ergebnismengen
ResultSet repräsentiert eine Ergebnismenge
stellt in Java einen Datenbank-Cursor dar.
ist Rückgabewert der Funktion executeQuery() aus
Statement, PreparedStatement und CallableStatement
bietet Zugang zu Datensätzen die vom DB-Server
zurückgeliefert werden (kann auch leer sein)
führt internen Datensatzzeiger (kann sich vor dem ersten und
hinter dem letzten Datensatz befinden)
27 / 50
JDBC
Literatur
Ergebnismengen
nach der Abfrage befindet sich das ReultSet vor dem ersten
Datensatz
Vorrücken durch next()
next() liefert boolschen Wert zurück (weitere Datensätze
vorhanden?)
da Satzzeiger sich vor dem ersten Satz befindet muss initial
next() aufgerufen werden
Daten können mit getXXX() abgerufen werden
als Parameter Namen oder Position einer Spalte (Pos. beginnt
bei 1)
28 / 50
JDBC
Literatur
Typkonvertierung
in JDBC können bei der Abfrage von Werten automatisch
Konvertierungen durchgeführt werden
getLong(), getString(), getInt() ...
Connection con ;
Statement stmt = con . createStatement ();
String s = " SELECT titel , preis FROM titel " ;
ResultSet res = stmt . execute ( s );
while ( res . next ()) {
System . out . println ( " Titel " + res . getString ( " titel " );
}
29 / 50
JDBC
Literatur
Metadaten
Informationen über Tabellen und über die Datenbank selbst
verschiedene Informationen über eine DB können ausgelesen
werden
ist nützlich wenn man allgemeine Abfragen hat und z.B. die
Anzahl der Spalten im Ergebnis nicht kennt
bei Tabellen: Anzahl Spalten, Spaltentyp, NULL erlaubt,
Spaltenname ...
gesamte Datenbank: welche Tabellen, akt. Verbindungen, sind
outer joins möglich ...
30 / 50
JDBC
Literatur
Metadaten von Tabellen
Klasse ResultSetMetaData
Resu ltSetM etaData meta = rs . getMetaData ();
getColumnCount() Anzahl der Spalten
getCatalogName(int column) Katalogname
getColumnTypeName(int column) Spaltentyp
getScale(int column) Genauigkeit der Spalte
isAutoincrement(int column) Autoincrement ?
isNullable(int column) darf NULL vorhanden sein?
31 / 50
JDBC
Literatur
Metadaten der Datenbank
Klasse DatabaseMetaData
DatabaseMetaData meta = con . getMetaData ();
getDatabaseProductName()
getMaxConnections()
getDriverVersion()
getTableTypes()
supportsOuterJoins()
...
32 / 50
JDBC
Literatur
Positionierung
seit JDBC 2.0 möglich sich in einer Ergebnismenge zurück zu
bewegen
außerdem direkt eine Zeile anwählbar
Konstanten aus dem ResultSet-Interface definieren
Positionierbarkeit
beim Erzeugen des Statements wird Konstante übergeben
FORWARD ONLY nur vorwärts
TYPE SCROLL INSENSITIVE vorwärts, rückwärts, absolut
bekommt Änderungen aus anderen Sitzung nicht mit
TYPE SCROLL SENSITIVE vorwärts, rückwärts, absolut
bekommt Änderungen aus anderen Sitzung mit
33 / 50
JDBC
Literatur
Positionierung
Methoden eines positionierbaren ResultSets
previous() zurück
first() erster Datensatz
last() letzter Datensatz
beforeFirst() vor den ersten
afterLast() nach den letzten
absolute(int) springe zu Nummer Datensatz
relative(int) verändere aktuelle Position
34 / 50
JDBC
Literatur
Verändern von Datensätzen
seit JDBC 2.0 aktueller Datensatz veränderbar über
updateXXX() mit konkretem Datentyp
CONCUR READ ONLY nicht änderbar
CONCUR UPDATETABLE änderbar
1. Statement Exemplar erzeugen
2. Anfrage ausführen ResultSet positionieren
3. Änderung über ResultSet-Methoden updateRow(),
deleteRow(), insertRow()
35 / 50
JDBC
Literatur
Verändern von Datensätzen
Connection con ;
Statement stmt = con . createStatement (
ResultSet . TYPE_SCROLL_INSENSITIVE ,
ResultSet . CONCUR_UPDATEABLE );
String s = " SELECT tit_id , preis
FROM titel WHERE tit_id = 2 " ;
ResultSet res = stmt . executeQuery ( sql );
rs . next ();
rs . updateFloat (2 ,50);
rs . updateRow ();
...
36 / 50
JDBC
Literatur
Größe der Ergebnismenge
entweder mit zwei Abfragen oder mit Positionierung von
JDBC 2.0
Result res = stmt . executeQuery (
" SELECT count (*) FROM titel " );
res . next ();
long length = res . getLong (1);
res . close ();
// eigentliche Anfrage
Statement stmt = con . createStatement (
ResultSet . TYPE_SCROLL_INSENSITIVE ,
ResultSet . CONCUR_READ_ONLY );
Result res = stmt . executeQuery (
" SELECT preis , name FROM titel " );
res . last ();
long length = res . getRow ();
res . first ();
// Zugriff auf Daten
37 / 50
JDBC
Literatur
Vorbereitetes SQL
Platzhalter für Parameter in Anweisungen
werden bei Ausführung mit Werten belegt dadurch
Anweisungen mehrfach verwendbar
Parameter werden durch ? definiert
Erzeugen eines PreparedStatements mit
prepareStatement()-Methode
SQL-Anweisung + Parameter Definition werden übergeben
mit setXXX()-Methoden werden Parameter mit Werten
belegt (XXX für Datentyp)
38 / 50
JDBC
Literatur
Vorbereitetes SQL
beim Erzeugen wird SQL-String an DBS geschickt, kompiliert
und zwischengespeichert mit Lücken für Parameter
erst beim Aufruf der setXXX()-Methoden gesetzt
setXXX() kann Parameter immer wieder neu setzen
die initial kompilierte Anweisung wird wiederverwendet nur
mit neuen Parametern
bessere Performance
39 / 50
JDBC
Literatur
Parameter setzen
setXXX() erwartet Index des Parameters und Wert
bei mehrfachem Ausführen müssen nicht alle Werte neu
belegt werden
Wert bleibt solange gültig bis er durch neuen ersetzt wird
Löschen der Parameter mit clearParameters()
NULL-Werte sind setzbar durch setNull() oder NULL
40 / 50
JDBC
Literatur
Parameter setzen
long titId ;
long words [];
String sql = " INSERT INTO stichworte_titel
VALUES (? ,?) " ;
PrepareStatement stmt = con . prepareStatement ( sql );
stmt . setLong (2 , titId );
for ( int i =0; words . length ; i ++) {
stmt . setLong (1 , words [ i ]);
stmt . executeUpdate ();
}
41 / 50
JDBC
Literatur
Stored Procedures
CallableStatement in JDBC abgeleitet von
PreparedStatement
prepareCall() erzeugt CallableStatment
Rückgabewerte müssen vor Ausführung definiert werden
registerOutParameter()
Parameter setzen setXXX()
Aufrufen von executeUpdate()
{ ? = call funktion (? , ?) }
{ call funktion (? , ?)}
42 / 50
JDBC
Literatur
Stored Procedures
Stored Functions besitzt einen Rückgabewert
Stored Procedures und Functions können OUT oder IN OUT
Parameter definieren
String isbn ;
int rank ;
String sql = " { ? = call ranking (?) } " ;
CallableSt atemen t call = con . prepareCall ( sql );
call . setString (2 , isbn );
call . re g i s t e r O u t P arameter (1 , Types . NUMERIC );
call . executeUpdate ();
rank = call . getInt (1);
43 / 50
JDBC
Literatur
Large Objects
große Daten in Datenbanken
zwei Typen BLOBs und CLOBs
in JDBC Schnittstelle zum Zugriff auf Large Objects
werden über Streams vom DBS gelesen, bzw. geschrieben
Schreiben vom Large Objects nur mit PreparedStatement
bzw. CallableStatement-Exemplaren
44 / 50
JDBC
Literatur
Zugriff auf BLOB und CLOB
Zugriff über getBlob() und getClob()
Setzen über setBinaryStream() da es keinen eigenen
Konstruktor gibt
NEU seit Java 6: createBlob(), und CreateClob()
PreparedSt atemen t stmt = con . prepareStatement (
" INSERT INTO MyTable column VALUES (?) " );
File file = new File ( " myImage . jpg " );
InputStream in = new FileInputStream ( file );
stmt . setBinaryStream ( 1 , in , ( int ) file . length ());
stmt . executeUpdate ();
45 / 50
JDBC
Literatur
Transaktionen
sind durch folgende Eigenschaften charakterisiert
Atomic (atomar): zu einer Transaktion können mehrere
primitive Änderungen gehören von denen entweder alle oder
keine augeführt wird
Consistent (kosistent): überführen Datenbank von einem
konsistenten Zustand in einen anderen konsitenten Zustand
Isolated (isoliert): Einzelschritte beliben für andere Sitzungen
verborgen
Durable (dauerhaft): Änderungen werden dauerhaft
gespeichert
46 / 50
JDBC
Literatur
Transaktionen
nach dem Öffnen einer Verbindung wird automatisch neue
Transaktion gestartet
Auto-Commit-Modus
nach jeder Ausführung wird die Änderung gespeichert
nach der Ausführung neue Transaktion
Commit-Modus kann über die Methode setAutoCommit()
beeinflusst werden
getAutoCommit() fragt Zustand ab
47 / 50
JDBC
Literatur
Transaktionen
liefert getAutoCommit() false muss man Transaktionen
selber steuern
commit() beendet Transaktion und speichert Änderungen
rollback() Änderungen die seit dem letztn commit()
gemacht wurden werden verworfen
Connection con =
DriverManager . getConnection ( url , user , password );
con . setAutoCommit ( false );
Statement stmt = con . createStatement ();
...
try {
stmt . executeUpdate ( up1 );
stmt . executeUpdate ( up2 );
con . commit ();
} catch ( SQLException e ) {
con . rollback ();
}
48 / 50
JDBC
Literatur
Übungsaufgaben
embedded Datenbank da einfach aufzusetzen
100% Java nur ein Jar und DB als 3 Dateien
hier H2 (http://www.h2database.com/)
Treibername: org.h2.Driver
Url-Syntax: “jdbc:h2:/tmp/testdb “ wobei “/tmp/testdb“ der
Dateiname der DB ist
Username ist “sa“, Passwort leer
Datenbank wird automatisch erzeugt
Webinterface auf dem lokalen Rechner
h2/bin/h2.jar muss zum Classpath hinzugefügt werden
49 / 50
JDBC
Literatur
Cay S Horstmann and Gary Cornell. Core Java. Revised and
Updated for Java SE 6; 8th ed. Prentice-Hall, Upper Saddle
River, NJ, 2008.
Christian Ullenboom. Java ist auch eine Insel. Galileo Computing,
7 edition, 2008. ISBN 978-3-8362-1146-8.
50 / 50
Herunterladen