Folien: JDBC

Werbung
Java Database Connectivity API / JDBC
Motivation
Design
Treiber
Grundlagen
Metadaten
Transaktionen
Exceptions
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
1
Motivation
• Problem: Zugriff auf DBMS nicht einheitlich
Anwendung
Anwendung
Anwendung
MySQL API
DB2 API
Oracle API
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
MySQL
DB2
Oracle
2
Motivation
• Lösung: Zwischenschicht
MySQL API
Anwendung
JDBC API
J
D
B
C
DB2 API
Oracle API
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
MySQL
DB2
Oracle
3
Design
•
•
•
•
•
Entwicklung seit: 1995
Erster Ansatz: Java erweitern
Zweiter Ansatz: Treiber der Datenbankhersteller
Vorbild: ODBC
Unterschiede:
– ODBC wenige Befehle, viele Optionen
– JDBC viele einfache Methoden
– ODBC nutzt void-Zeiger
– Java kennt keine Zeiger
•
Flexibilität: JDBC erlaubt beliebige Zeichenfolgen
– Anpassung an Datenbank möglich.
• Optimierung ✔
• Bindung ✖
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
4
Design
Java Anwendung
JDBC-Treibermanger
JDBC/ODBC-Brücke
JDBC-Treiber
ODBC-Treiber
Datenbank
Datenbank
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
5
Treiber, Typ 1 und 2
•
Typ 1: Brücke
– zB: JDBC/ODBC
• ODBC ist verbreitet ✔
• Testen, Experimentieren
• Windows Plattformen
– Leistung ✖
– Wartung ✖
– Wenn kein JDBC-Treiber
verfügbar ist
•
B
r
ü
c
k
e
JDBCAnwendung
ODBC
ODBCTreiber
DB
Client
Server
Typ 2: Partial Java Driver
– Gibt Aufruf an native
API weiter
– DB und OS abhängig ✖
– Nutzer braucht
plattformabhängige API ✖
JDBCAnwendung
A
P
I
DB
Client
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
Server
6
Treiber, Typ 3 und 4
•
Typ 3: Reiner Java Treiber zu Middleware
–
–
–
–
•
Portabel ✔
DB unabhängig ✔
Flexibel, mehrere DB möglich ✔
DB abhängiger Teil in Middleware
Typ 4: Reiner Java Treiber zur DB
JDBCAnwendung
M
W
DB
Client
Server
Server
– Portabel ✔
– Schnell ✔
JDBC– Verbindung
Anwendung
• Netz
• File I/O
• Embedded
Client
– Client braucht DB abhängige Treiber ✖
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
DB
Server
7
Treiber, Installation
• Download
– http://developers.sun.com/product/jdbc/drivers
– Datenbankhersteller
• Installation
– Eintragen in den Klassenpfad
• Laden eines JDBC Treibers
– System Property: jdbc.drivers
• java-Djdbc.drivers=org.apache.derby.jdbc.EmbeddedDriverXyz
• System.setProperty("jdbc.drivers",
"org.apache.derby.jdbc.EmbeddedDriver");
– Manuelles laden der Treiberklasse
• Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
– Automatisch durch DriverManager
• Java Service: java.sql.Driver
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
8
Verbindungsaufbau
• DriverManager
– Verwaltet registrierte Treiber, baut Verbindungen auf
• ConnectiongetConnection(Stringurl, String
user, String password)
• Datenbank URL
– Aufbau: jdbc:<subprotrokoll>:<subname>
• jdbc:<Datenbanktreiber>:<treiberspezifische
Angaben>
– Derby
• jdbc:derby:/path/to/Database
• jdbc:derby:Database
– MySQL
• jdbc:mysql://<host>:<port>/<Database>
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
9
Verbindung
• Connection: Verwaltet Verbindung (Session) zur DB
– close()
• Schließen der Verbindung
– commit()
• Bestätigen vorangegangener Änderungen, Standard
ist auto-commit
– StatementcreateStatement()
Statement stat = con.createStatement();
stat.executeUpdate("INSERT INTO test VALUES ('Hallo')");
– PreparedStatementprepareStatement(Stringsql)
PreparedStatementstat = con
.prepareStatement("INSERT INTO test VALUES ('Hallo')");
...
stat.executeUpdate();
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
10
Statement
•
ResultSetexecuteQuery(Stringsql)
Keine Parameter!
SQL-Injection
– Ausführen einer SQL-Abfrage (SELECT)
•
intexecuteUpdate(Stringsql)
– Ausführen eines Updates (UPDATE, INSERT, DELETE)
– Liefert die Anzahl der betroffenen Zeilen
•
booleanexecute(Stringsql)
– Ausführen beliebiger SQL-Anweisungen
– Liefert truewenn eine Ergebnismenge geliefert wurde
•
intgetUpdateCount()
– Anzahl der betroffenen Zeilen, oder -1 wenn Anweisung keinen
Zähler hatte
•
ResultSetgetResultSet()
– Ergebnismenge der letzten Abfrage, oder null wenn keine
Ergebnismenge geliefert wurde
•
voidclose()
– Gibt alle JDBC Ressourcen frei
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
11
PreparedStatement
•
voidset<Typ>(int n, <Typ> x)
– Setzen des Parameters an der Stelle n (1..m)
•
voidclearParameters()
– Löschen aller Parameterwerte
•
ResultSetexecuteQuery()
– Ausführen der vorübersetzten SQL-Anfrage (SELECT)
•
intexecuteUpdate()
– Ausführen des vorübersetzten Updates (UPDATE, INSERT, DELETE)
– Gibt die Anzahl betroffener Zeilen zurück
PreparedStatementstat;
stat = con.prepareStatement("INSERT INTO test VALUES (?,?)");
stat.setString(1, "Hallo");
stat.setString(2, "Welt");
stat.executeUpdate();
stat.setString(2, "Jane");
stat.executeUpdate();
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
12
CallableStatement
•
•
Ausführen von DB-Prozeduren (SQL storedprocedures)
Parameterlose Prozedur
– {callprocedure_name }
•
Prozedur
– {callprocedure_name(?,?,...)}
•
Funktion
– { ? = callprocedure_name(?,?,...) }
•
•
Eingangsparameter analog zu PreparedStatement
Ausgabeparameter müssen registriert werden
– voidregisterOutParameter(intindex, intsqlType)
CallableStatementcs = con
.prepareCall("{ CALL GET_NUMBER_FOR_NAME(?, ?) }");
cs.registerOutParameter(2, java.sql.Types.INTEGER);
cs.setString(1, "Duke");
cs.execute();
intnumber = cs.getInt(2);
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
13
ResultSet
• Zeilenweise abarbeiten der Ergebnistabelle
– booleannext()
• Anspringen der nächsten Zeile
• true solange gültige Zeile erreicht wird
• ResultSet beginnt vor der ersten Zeile
– <Typ>get<Typ>(int spalte)
– <Typ>get<Typ>(StringspaltenName)
– booleanwasNull()
• true wenn letzter Wert SQL-NULL war
– intfindColumn(StringspaltenName)
Nr Name Age
getInt(3) => 25
wasNull() =>false
getString("Name") => Max
findColumn("Nr") => 1
1
Max
25
2
Kurt
27
...
...
...
next()
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
14
ResultSet Fortsetzung
•
booleanfirst()
– Erste Zeile im ResultSet
– true wenn gültige Zeile erreicht
•
voidbeforeFirst()
– Vor die erste Zeile im ResultSet
•
boolean last()
– Letzte Zeile im ResultSet
– true wenn gültige Zeile erreicht
•
voidafterLast()
– Nach letzter Zeile im ResultSet
•
booleanabsolute(introw)
– Eine Zeile anspringen
• row> 0 ... von oben (1 erste Zeile, 2 zweite Zeile, ...)
• row< 0 ... von unten (-1 letzte Zeile, -2 vorletzte Zeile, ...)
– true wenn gültige Zeile erreicht
•
intgetRow()
– Nummer der aktuellen Zeile
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
15
Typen
SQL-Typ
Java-Typ
CHAR, VARCHAR, LONGVARCHAR
String
NUMERIC, DECIMAL
java.math.BigDecimal
BIT
boolean
TINYINT
byte
SMALLINT
short
INTEGER
int
BIGINT
long
REAL
float
FLOAT, DOUBLE
double
BINARY, VARBINARY, LONGVARBINARY
byte[]
DATE
java.sql.Date
TIME
java.sql.Time
TIMESTAMP
java.sql.Timestamp
...
siehe JSR-221, Appendix B, Date
Type ConversionTables
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
16
Metadaten, Datenbank
•
Erstellen über Verbindung
– DatabaseMetaData<Connection>.getMetaData()
•
Allgemeines
–
–
–
–
•
ConnectiongetConnection()
String getURL()
String getUserName()
booleanisReadOnly()
Eigenschaften
– boolean supportsANSI92EntryLevelSQL()
– booleansupportsTransactions()
– booleansupportsGroupBy()
•
Beschränkungen
– intgetMaxStatementLength()
– intgetMaxStatements()
– intgetMaxConnections()
0 .. kein Limit oder
unbekannt
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
17
Metadaten, Tabellen
•
•
ResultSetgetTables(Stringcatalog, String schema,
String table, String[] types)
ResultSetgetColumns(Stringcatalog, String schema,
String table, String column)
– catalog: Name des Katalogs
• "" Tabellen ohne Katalog, null Katalognamen nicht
berücksichtigen
– scheme: Schemaname
• "" Tabellen ohne Schema, null nicht berücksichtigen
– table: Tabellenname
• null nicht berücksichtigen
– column: Spaltenname
• null nicht berücksichtigen
– types:
• zB: "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
"LOCAL TEMPORARY", "ALIAS", "SYNONYM"
• null nicht berücksichtigen
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
18
Metadaten, Ergebnismenge
•
Erstellen
– ResultSetMetaData<ResultSet>.getMetaData()
•
Eigenschaften
–
–
–
–
–
–
Nr Name Title ... Age
intgetColumnCount()
1
String getColumnName(int column)
2
intgetColumnType(int column)
...
String getColumnTypeName(int column)
String getTableName(int column)
booleanisCurrency(intcolumn)
getColumnCount() => 3
getColumnName(1) => "Nr"
getColumnType(3) => 4 // INTEGER
getColumnTypeName(3) => "int"
getTableName(2) => "users"
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
Max
DI
... 30
Susi
Mag ... 28
...
...
... ...
SELECT Nr,
Name, Age
FROM users;
Nr Name Age
1
Max
30
2
Susi
28
...
...
...
19
Transaktionen
•
Standard: auto-commit, jedes Statement eine Transaktion
– boolean<Connection>.getAutoCommit()
– void<Connection>.setAutoCommit(booleanac)
•
•
Transaktion startet automatisch
Transaktion abschießen
Auto-Commit
– void<Connection>.commit()
•
Transaktion rücksetzen (zB: SQLException)
– void<Connection>.rollback()
Connection con;
...
try {
con.setAutoCommit(false);
Statement stat = con.createStatement();
stat.executeUpdate("INSERT ...");
stat.executeUpdate("INSERT ...");
stat.executeUpdate("UPDATE ...");
con.commit();
} catch (SQLException e) { con.rollback(); }
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
Savepoints
TransactionIsolation
NONE
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE
20
Exceptions
SQLException
SQLNonTransient
Exception
Erneuter
Versuch wird
fehlschlagen
SQLTransient
Exception
Erneuter
Versuch kann
durchgehen
SQLRecoverable
Exception
Erneuter Versuch
nach Eingriffen
kann durchgehen
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
21
JavaDB, Derby
• Seit Java 6.0 mitgeliefert
• Web-Seite: http://db.apache.org/derby
• Umgebungsvariablen
– JAVA_HOME=Pfad zur Java JDK Installation
– DERBY_HOME=Pfad zur Derby Installation
– PATH um DERBY_HOME/bin erweitern
• JARs in DERBY_HOME/lib
–
–
–
–
–
derby.jar, Engine, genügt für embedded DB
derbynet.jar, Netzzugriff, Serverseitig
derbyclient.jar, Netzzugriff, Clientseitig
derbytools.jar, Verwaltungs-Werkzeuge
derbyrun.jar verweist auf:
• derby.jarderbyclient.jarderbytools.jarderbynet.jar
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
22
JavaDB, Derby, Kommandozeilen-Werkzeuge
• Systeminformation: sysinfo
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
23
JavaDB, Derby, Kommandozeilen-Werkzeuge
• Kommandozeilenwerkzeug: ij
Verbinden zu
(und erzeugen
einer) Datenbank
Tabelle erzeugen
Beschreibung
einer Tabelle
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
24
JavaDB, Derby, Kommandozeilen-Werkzeuge
• Kommandozeilenwerkzeug: ij
Abfragen von
Datensätzen
Aktualisieren
eines Datensatzes
Löschen einer
Tabelle
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
25
Zusammenfassung
•
Datenbankunabhängigkeit
– Zwischenschicht -> einfachere Programmentwicklung
– Treiberschnittstelle (min. SQL 92 entrylevel)
• 4 Treiberarten
– Brücke (zB: JDBC -> ODBC)
– Teilweise Java
– Java zu Middleware
– Java zu Datenbank
•
Beliebige SQL-Kommandos absetzbar
– Optimierung vs. Datenbankunabhängigkeit
•
Statements
– PreparedStatement
• Vorkompiliert, mit Parametern (Sicher gegen SQL-Injection)
– Statement
• Statisch, Abfragen vom Benutzer, keine Parameter
– CallableStatement
• StoredProcedures, mit IN, OUT und INOUT Parametern
Praktikum aus Softwareentwicklung 2 © Markus Löberbauer
26
Herunterladen