Kapitel 5 - Webarchiv ETHZ / Webarchive ETH

Werbung
Kapitel 5
Java-Anbindung für objektrelationale
Datenbanken
Java und Datenbanken
JDBC
SQLJ
Disclaimer
Dieses Kapitel basiert auf dem folgenden Buch, welches auch zur weiteren
Vertiefung empfohlen wird:
Can Türker:
SQL:1999 & SQL:2003 —
Objektrelationales SQL, SQLJ & SQL/XML.
dpunkt-Verlag, Heidelberg, 2003.
ISBN: 3-89864-219-4
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-2
Programmiersprache Java
z
Java ist
–
–
–
–
–
objektorientiert (Klassen als Abstraktionskonzept)
einfach
„ automatisierte Speicherverwaltung
„ Verzicht auf Zeiger und Goto
robust und sicher
„ strenge Typisierung
„ Laufzeitüberpüfung von Zugriffen
interpretiert und dynamisch
architekturneutral und portabel
„ Plattformunabhängiger Zwischencode (Bytecode)
„ Programme sind ohne Änderungen ablauffähig unter Windows, Unix, ...
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-3
Java und Datenbanken
z
Einsatz von Java
–
–
–
z
auf Client-Seite:
„ DB-Anwendungen
auf Server-Seite:
„ DB-Erweiterungen (benutzerdefinierte Prozeduren, Funktionen &
Datentypen)
auf Middleware-Ebene:
„ Anwendungslogik (JavaBeans)
Anbindung Java - Datenbank
–
–
JDBC (Java Database Connectivity; Call-Level-Schnittstelle)
SQLJ (Embedded SQL in Java)
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-4
Java und Datenbankanwendungen
Benutzerschnittstelle
CORBA, HTTP, ...
Benutzerschnittstelle
DBDB-Client
Anwendungslogik
Anwendungslogik
JDBC,
SQLJ
DB-Schnittstelle
DB-Schnittstelle
DBMS-Protokoll
DBDB-Server
DBDB-Client
AnwendungsAnwendungsServer
DBMS-Protokoll
DB
DB
DBDB-Server
Benutzerdefinierte
Prozeduren, Funktionen
& Datentypen in Java
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-5
JDBC
z
Entwicklung von Sun
z
JDBC 1 definiert die Basisfunktionalität von JDBC
–
–
–
z
JDBC 2 erweitert JDBC 1 um
–
–
–
–
z
Herstellen von Verbindungen zu SQL-Datenbanken
Ausführen von SQL-Anweisungen
Verarbeiten von Anfrageergebnissen
scroll- und änderbare Ergebnismengen
Batch-Änderungen
SQL:1999-Datentypen
benutzerdefinierte Typabbildungen
JDBC 3 unterstützt weitere SQL:1999-Funktionalität
–
–
Sicherungspunkte
Änderungsmethoden für Spalten von konstruierten bzw. benutzerdefinierten
Datentypen
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-6
JDBC - Überblick
z
Datenbankzugriffsschnittstelle für Java
–
–
–
–
z
abstrakt und datenbankneutral
vergleichbar mit ODBC
Low-Level-API: direkte Nutzung von SQL
Java-Package java.sql
Klassen
–
–
–
–
DriverManager: Einstiegspunkt, Laden von Treibern
Connection: Datenbankverbindung
Statement: Ausführung von Anweisungen über eine Verbindung
ResultSet: verwaltet Ergebnisse einer Anfrage, Zugriff auf einzelne Spalten
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-7
Datenbankanbindung - Ablauf
z
Aufbau einer Verbindung zur Datenbank
–
–
z
Senden einer SQL-Anweisung
–
–
z
Angabe der Verbindungsinformationen
Auswahl und dynamisches Laden des Treibers
Definition der Anweisung
Belegung von Parametern
Verarbeiten der Anfrageergebnisse
–
–
Navigation über Ergebnisrelation
Zugriff auf Spalten
DriverManager
getConnection()
Connection
createStatement()
Statement
executeQuery()
ResultSet
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-8
JDBC - Beispiel (in Oracle)
import java.sql.*;
import java.util.*;
class Kunden {
public static void main (String args []) throws SQLException {
// Lade Oracle JDBC Treiber und stelle Verbindung zur Datenbank ORDB her
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection con = DriverManager.getConnection("jdbc:oracle:oci8:@", "scott", "tiger");
// Erzeuge und führe SQL-Anweisung aus & iteriere durch die Ergebnismenge
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT Name, Anschrift, Telefone FROM Kunde");
while (rs.next()) {
Struct a = (Struct) rs.getObject(2);
Object attrs [] = a.getAttributes();
Array t = rs.getArray(3);
System.out.println("Kundenname : " + rs.getString(1));
System.out.println("Wohnort
: " + attrs[3] + ", " + attrs[4]);
System.out.println("Telefon
: " +(String)((Object[])t.getArray())[0].toString());
}
rs.close(); stmt.close(); con.close(); // Schliessen aller Resourcen
}
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-9
Treiberregistrierung
z
Treiber laden (2 Varianten)
Class.forName("com.company.DBDriver");
DriverManager.registerDriver(new com.company.DBDriver());
Oracle
oracle.jdbc.driver.OracleDriver
DB2
COM.ibm.db2.jdbc.app.DB2Driver
Informix
com.informix.jdbc.IfxDriver
PostgreSQL
org.postgresql.Driver
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-10
Verbindungsaufbau
z
Verbindung herstellen
String url = "jdbc:subprotocol:datasource";
String user = "scott";
String passwd = "tiger";
Connection con = DriverManager.getConnection(url, user, passwd);
–
JDBC-URL spezifiziert
„ Datenquelle/Datenbank
„ Verbindungsmechanismus (Protokoll, Server-Host und Port)
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-11
Ausführung einer DB-Anfrage bzw. DB-Änderung
z
Anweisungsobjekt (Statement) erzeugen
Statement stmt = con.createStatement();
z
Anweisung ausführen
String queryStmt = "SELECT Name, Anschrift FROM Kunde";
ResultSet rset = stmt.executeQuery(queryStmt);
–
Klasse java.sql.Statement
„ Ausführung von Anfragen (SELECT) mit executeQuery
„ Ausführung von Änderungen (DELETE, INSERT, UPDATE) mit
executeUpdate (liefert Anzahl der betroffenen Tupel/Objekte)
String delStmt = "DELETE Kunde WHERE KNr = 1311";
int rows = stmt.executeUpdate(delStmt);
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-12
Ergebnisverarbeitung
z
Navigation über Ergebnismenge (Cursor-Prinzip)
while (rset.next()) {
// Verarbeitung der einzelnen Tupel
...
}
z
Zugriff auf Spaltenwerte über getXXX-Methoden
–
über Spaltenindex
String name = rset.getString(1);
–
über Spaltenname
String name = rset.getString("Name");
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-13
Typabbildung von
Java nach SQL
Typabbildung von
SQL nach Java
SQL
getget-Methode
JavaJava-Typ
JavaJava-Typ
setset-Methode
SQL
SMALLINT
INTEGER
BIGINT
NUMERIC
DECIMAL
FLOAT
REAL
DOUBLE PRECISION
CHAR
VARCHAR
BIT
VARYING BIT
DATE
TIME
TIMESTAMP
getShort
getInt
getLong
getBigDecimal
getBigDecimal
getDouble
getFloat
getDouble
getString
getString
getBoolean
getBytes
getDate
getTime
getTimestamp
short
int
long
BigDecimal
BigDecimal
double
float
double
String
String
boolean
byte[]
Date
Time
Timestamp
byte
short
int
long
BigDecimal
float
double
String
boolean
byte[]
Date
Time
Timestamp
setByte
setShort
setInt
setLong
setBigDecimal
setFloat
setDouble
setString
setBoolean
setBytes
setDate
setTime
setTimestamp
SMALLINT
SMALLINT
INTEGER
BIGINT
NUMERIC
REAL
DOUBLE
VARCHAR
BIT
VARYING BIT
DATE
TIME
TIMESTAMP
Abbildung der benutzerdefinierten Datentypen von SQL:2003 wird später
später vorgestellt
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-14
Fehlerbehandlung
z
Fehlerbehandlung mittels Exception-Mechanismus
z
SQLException für alle SQL- und DBMS-Fehler
try {
// Aufruf von JDBC-Methoden
...
} catch (SQLException exc) {
System.out.println("SQLException: " + exc.getMessage());
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-15
Transaktionssteuerung
z
Methoden von Connection
–
–
z
Auto-Commit-Modus
–
–
–
z
commit()
rollback()
implizites Commit nach jeder
Anweisung
Transaktion besteht nur aus einer
Anweisung
Umschalten mittels
setAutoCommit(boolean)
Transaktionsisolationsebenen
–
setzen mittels setTransactionLevel(int)
try {
// AutoCommit-Modus ausschalten
con.setAutoCommit(false);
// DML-Anweisungen
...
// COMMIT ausführen
con.commit();
} catch (SQLException exc) {
// Änderungen zurücknehmen
con.rollback();
}
TRANSACTION_NONE
TRANSACTION_READ_UNCOMMITTED
TRANSACTION_READ_COMMITTED
TRANSACTION_READ_SERILIZABLE
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-16
Anfrageformen
z
Statement
–
–
z
PreparedStatement
–
–
–
z
Basisklasse für alle Anweisungen
Verarbeitung einfacher SQL-Anweisungen ohne Parameter
Kapselung einer vorkompilierten Anweisung
parametrisierbar
Verwendung: wiederholte Ausführung einer Anweisung (mit verschiedenen
Parametern)
CallableStatement
–
Aufruf von gespeicherten Prozeduren mit Parametern
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-17
Vorübersetzte Anweisungen
z
java.sql.PreparedStatement
–
–
z
Beschleunigung der Ausführung von Anweisungen durch Vorübersetzung und
wiederholten Aufruf mit verschiedenen Parametersätzen
Anweisungsobjekt (PreparedStatement) erzeugen
String insStmt = "INSERT INTO Kunde VALUES (?, ?)";
PreparedStatement stmt = con.prepareStatement(insStmt);
z
Anweisungsparameter
durch "?" markiert
Belegung der Parameter mittels setXXX-Methoden
stmt.setString(1, "George");
stmt.setFloat(2, 4500.00);
z
Anweisung ausführen
stmt.executeUpdate(insStmt);
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-18
Aufruf von gespeicherten Prozeduren
z
java.sql.CallableStatement
–
z
Aufruf von gespeicherten Prozeduren (Stored Procedures)
Anweisungsobjekt (CallableStatement) erzeugen und Parameter setzen
String callStmt = "{CALL TestProc(?, ?)}";
CallableStatement stmt = con.prepareCall(callStmt);
stmt.setInt(1, 42);
z
Registrierung des SQL-Typs der OUT-Parameter & Auslesen der
Ergebniswerte mit getXXX-Methoden
stmt.registerOutParameter(2, java.sql.Types.FLOAT);
stmt.executeUpdate();
double res = stmt.getDouble(2);
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-19
JDBC-Interfaces
ResultSet
executeQuery
executeUpdate
Statement
executeQuery
executeUpdate
getXXX
createStatement
PreparedStatement
setXXX
Data Types
getXXX
DriverManager
prepareStatement
getConnection
Connection
prepareCall
CallableStatement
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-20
Neue Features in JDBC 2
z
Core API - Bestandteil von Java 2
–
–
–
–
z
Scrollbare und änderbare ResultSets
Batch-Updates
SQL-99-Datentypen
Benutzerdefinierte Typabbildung
Optional API
–
–
–
–
Nutzung von Namensdiensten (JNDI)
Connection Pooling
Verteilte Transaktionen
RowSets
// Array
public Array ResultSet.getArray()
public void PreparedStatement.setArray()
public String Array.getBaseTypeName()
public Object Array.getArray()
// Struct
public Object ResultSet.getObject()
public void PreparedStatement.setObject()
public Object[] Struct.getAttributes()
public String Struct.getSQLTypeName()
// Ref
public Ref ResultSet.getRef()
public void PreparedStatement.setRef()
public String Ref.getBaseTypeName()
// Object
public Object ResultSet.getObject()
public void PreparedStatement.setObject()
public String Object.toString()
public Object Object.clone()
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-21
Scrollbare und änderbare Ergebnismengen
z
ResultSet-Typen:
–
–
–
z
TYPE_FORWARD_ONLY (vorwärtsscrollbar & nicht änderbar)
TYPE_SCROLL_INSENSITIVE (vorwärts-/rüchwärtsscrollbar & nicht änderbar)
TYPE_SCROLL_SENSITIVE (vorwärts-/rüchwärtsscrollbar & änderbar)
Concurrency-Typen (CONCUR_READ_ONLY,
CONCUR_READ_ONLY, CONCUR_UPDATABLE)
CONCUR_UPDATABLE)
Statement stmt = con.createStatement(ResultSetTyp, ConcurrencyTyp);
ResultSet rs = stmt.executeQuery(QueryString);
–
–
–
–
–
Ändern im ResultSet: updateXXX(Spalte, Wert)
Ändern in der DB: updateRow()
Löschen aus dem ResultSet und der DB: deleteRow()
Einfügen ins ResultSet: moveToInsertRow()+ updateXXX(Spalte, Wert)
Einfügen in die DB: insertRow()
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-22
JDBC - Beispiel (änderbare Ergebnismengen)
import java.sql.*;
import java.util.*;
class KundenKredit {
public static void main (String args []) throws SQLException {
// Lade Oracle JDBC Treiber und stelle Verbindung zur Datenbank ORDB her
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection con = DriverManager.getConnection("jdbc:oracle:oci8:@", "scott", "tiger");
// Erzeuge und führe SQL-Anweisung aus & iteriere durch die Ergebnismenge
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT Name, Kredit FROM Kunde");
while (rs.next()) {
System.out.println("Kundenname
: " + rs.getString(1));
System.out.println("Bisheriger Kreditrahmen: " + rs.getFloat(2));
rs.updateFloat(2, rs.getFloat(2) + 100.0f); // Attribut des aktuellen Tupels ändern
rs.updateRow();
// Änderung in die Datenbank übernehmen
}
rs.close(); stmt.close(); con.close();
// Schliessen aller Resourcen
}
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-23
ResultSet-Methoden zum Scrollen
Methoden
CursorCursor-Position
ResultSet.beforeFirst();
Vor dem ersten Tupel
ResultSet.first();
Erstes Tupel
ResultSet.beforeFirst();
Nach dem letzten Tupel
ResultSet.next();
Nächstes Tupel
ResultSet.previous();
Vorheriges Tupel
ResultSet.absolute(p);
Tupels auf Indexposition p
ResultSet.relative(p);
Tupels auf Indexposition (aktuelle Position + p)
ResultSet.moveToCurrentRow();
Aktuelles Tupel
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-24
Batch-Updates
// Autocommit ausschalten
con.setAutoCommit(false);
// Autocommit ausschalten
con.setAutoCommit(false);
Statement stmt = con.createStatement();
PreparedStatement stmt =
con.createStatement(UpdateString);
// Batch-Aufträge sammeln
stmt.addBatch(UpdateString1);
...
stmt.addBatch(UpdateStringN);
// Batch-Auftrag ausführen
int[] n = stmt.executeBatch();
// Parameter setzen
stmt.setXXX(Spalte, Wert);
// Auftrag dem Batch hinzufügen
stmt.addBatch();
...
// Parameter setzen
stmt.setXXX(Spalte, Wert);
// Auftrag dem Batch hinzufügen
stmt.addBatch();
// Batch-Auftrag ausführen
int[] n = stmt.executeBatch();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
Typabbildung von
Java nach SQL
Typabbildung von
SQL nach Java
SQL
BLOB
CLOB
ARRAY
ROW
REF
DistinctDistinct-Typ
Strukturierter Typ
5-25
getget-Methode JavaJava-Typ
JavaJava-Typ setset-Methode
getBlob
getClob
getArray
getObject
getRef
getX
getObject
Blob
Clob
Array
Struct
Ref
X
Struct
Blob
Clob
Array
Struct
Ref
X
Struct
setBlob
setClob
setArray
setObject
setRef
setX
setObject
SQL
BLOB
CLOB
ARRAY
ROW
REF
DistinctDistinct-Typ
Strukturierter Typ
X ist der Basisdatentyp,
Basisdatentyp, der einem DistinctDistinct-Typ zugrunde liegt!
liegt!
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-26
Illustration der Abbildung von SQL-Arrays nach Java
ResultSet
getArray(i)
getArray(i)
SQLSQL-Arraywert
JavaJava-ArrayArrayObjekt
Java-Array-Lokator
(Referenz auf SQL-Arraywert)
getArray()
getArray()
JavaJavaObjekt
JavaJavaObjekt
...
JavaJavaObjekt
Materialisierte
Array-Felder
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-27
Java-Repräsentation von SQL-Arrays
z
Schnittstelle Array definiert Java-Repräsentant des SQL-Datentyps ARRAY
–
–
–
z
SQL-Arraywert wird mit der Methode getArray gelesen und implizit in ein
Array-Objekt umgewandelt
–
z
Objekt der Klasse Array repräsentiert einen logischen Zeiger (Lokator) auf
einen SQL-Arraywert
Objekt enthält jedoch nicht die Feldwerte des SQL-Arrays
Feldwerte müssen mit Methoden der Klasse Array materialisiert explizit
werden, wenn dies gewünscht ist
Genauer gesagt wird der logische Zeiger auf den SQL-Arraywert im ArrayObjekt aufgebaut
Schreiben eines Array-Objekts erfolgt mit der Methode setArray
–
wandelt implizit das Array-Objekt in einen SQL-Arraywert um
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-28
Methoden zum Verarbeiten von SQL-Arrays
Methoden
Array
Array
Array
Array
Object[]
ResultSet.getArray(int pos)
ResultSet.getArray(String name)
CallableStatement.getArray(int pos)
CallableStatement.getArray(String name)
Array.getArray()
Array.getArray()
int
Array.getArray(long pos, int länge)
länge)
Array.getBaseType()
Array.getBaseType()
String
Array.getBaseTypeName()
Array.getBaseTypeName()
Object[]
Array.getResultSet()
ResultSet Array.getResultSet()
länge)
ResultSet Array.getResultSet(long pos, int länge)
void
PreparedStatement.setArray(int pos, Array wert)
wert)
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-29
Methoden der Schnittstelle Array
z
getArray materialisiert den durch das Array-Objekt repräsentierte SQLArraywert
–
liefert ein Array von Java-Objekten, welche die einzelnen Felder des SQL-Arrays
darstellen
z
getBaseType liefert den Java-Typwert des Elementtyps
z
getBaseTypeName gibt den Namen des SQL-Elementtyps aus
z
getResultSet liefert eine zweispaltige Ergebnismenge, die für jedes
Arrayfeld eine eigene Zeile enthält
–
–
erste Spalte weist die Position des Elements im Array auf
zweite Spalte enthält den Wert des Elements
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-30
Beispiel für das Verarbeiten von SQL-Arrays (1)
String str = "SELECT Name, Telefone FROM Mitarbeiter";
ResultSet rs = stmt.executeQuery(str);
while (rs.next())
{
// lies SQL-Array in Java-Array-Objekt
Array tarray = rs.getArray(2);
// extrahiere Arrayfelder
String[] telnr = (String[]) tarray.getArray();
// gib Namen des Mitarbeiters aus
System.out.println(”Telefonnummern von ” + rs.getString(1));
// gib Arrayfelder aus
for(int i = 0; i < telnr.length; i++)
System.out.println(i + ”. Nummer: ” + telnr[i]);
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-31
Beispiel für das Verarbeiten von SQL-Arrays (2)
// erzeuge Java-Repräsentant für einen SQLArraywert
Object [] telefonnummern = new Object [2];
telefonnummern[0] = "004116321172";
telefonnummern[1] = "00493916712020";
Array telArray = new Array(telefonnummern);
// erzeuge vorbereitetes Anweisungsobjekt
String str = "UPDATE Mitarbeiter SET Telefone = ? WHERE ID = 170302";
PreparedStatement ps = con.prepareStatement(str);
// belege arraywertige Spalte und führe Änderung aus
ps.setArray(1, telArray);
ps.execute();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-32
Illustration der Abbildung von SQL-Referenzen nach Java
ResultSet
getRef(i)
getRef(i)
SQLSQL-Referenzwert
JavaJava-RefRefObjekt
Java-Ref-Lokator
(Referenz auf SQL-Referenzwert)
getObject()
getObject()
SQLSQL-Objektwert
JavaJava-StructStructObjekt
Java-Struct-Lokator
(Referenz auf SQL-Objektwert)
getAttributes()
getAttributes()
JavaJavaObjekt
JavaJavaObjekt
...
JavaJavaObjekt
Materialisierte
Objektattribute
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-33
Java-Repräsentation von SQL-Referenzen
z
Schnittstelle Ref definiert Java-Repräsentant des SQL-Datentyps REF
–
–
–
z
SQL-Referenzwert wird mit der Methode getRef gelesen und implizit in
ein Ref-Objekt umgewandelt
–
z
Objekt der Klasse Ref repräsentiert einen logischen Zeiger (Lokator) auf einen
SQL-Referenzwert
Objekt enthält jedoch nicht den tatsächlichen SQL-Referenzwert
Feldwerte müssen mit Methoden der Klasse Array materialisiert explizit
werden, wenn dies gewünscht ist
Genauer gesagt wird der logische Zeiger auf den SQL-Referenzwert im RefObjekt aufgebaut
Schreiben eines Ref-Objekts erfolgt mit der Methode setRef
–
wandelt implizit das Ref-Objekt in einen SQL-Referenzwert um
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-34
Methoden zum Verarbeiten von SQL-Referenzen
Methoden
Ref
Ref
Ref
Ref
Object
Object
void
String
void
ResultSet.getRef(int pos)
ResultSet.getRef(String name)
CallableStatement.getRef(int pos)
CallableStatement.getRef(String name)
Ref.getObject()
Ref.getObject()
Ref.getObject(Map abbildung)
abbildung)
Ref.setObject(Object o)
Ref.getBaseTypeName()
Ref.getBaseTypeName()
PreparedStatement.setRef(int pos, Ref wert)
wert)
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-35
Methoden der Schnittstelle Ref
z
getObject liefert die von dem Ref-Objekt referenzierte Instanz eines
strukturierten Typs
–
–
z
setObject setzt den Wert eines referenzierten Objekts
–
z
bildet diese Instanz anhand der Typabbildungstabelle in den
korrespondierenden Java-Typ ab
falls es keinen passenden Eintrag in der Typabbildungstabelle gibt, erfolgt eine
Standardabbildung in ein Struct-Objekt
wandelt diesen in eine Instanz eines strukturierten Typs um
getBaseTypeName liefert den Namen des SQL-Typs der referenzierten
Instanz eines strukturierten Typs
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-36
Beispiel für das Verarbeiten von SQL-Referenzen (1)
String str = "SELECT Name, Vorgesetzter FROM Mitarbeiter";
ResultSet rs = stmt.executeQuery(str);
while (rs.next())
{
// lies Referenzspalte
Ref vref = rs.getRef(2);
// ermittle referenziertes Objekt
Struct vstruct = (Struct) vref.getObject();
// extrahiere Objektattribute
Object vatts [] = vstruct.getAttributes();
// gib das erste Objektattribut (Name) aus
System.out.println (vatts[0] + ” ist Boss von ” + rs.getString(1));
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-37
Beispiel für das Verarbeiten von SQL-Referenzen (2)
// ermittle Objektreferenz
String str = "SELECT oid FROM Mitarbeiter Where ID = 131169";
ResultSet rs = stmt.executeQuery(str):
rs.next();
Ref vorgesetzter = rs.getRef(1);
// erzeuge vorbereitetes Anweisungsobjekt
str = "UPDATE Mitarbeiter SET Vorgesetzter = ? WHERE ID = 190697";
PreparedStatement ps = con.prepareStatement(str);
// belege referenzwertige Spalte und führe Änderung aus
ps.setRef(1, vorgesetzter);
ps.execute();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-38
Illustration der Abbildung von SQL-Tupeln nach Java
ResultSet
getObject(i)
getObject(i)
SQLSQL-Tupelwert
JavaJava-StructStructObjekt
Java-Struct-Lokator
(Referenz auf SQL-Tupelwert)
getAttributes()
getAttributes()
JavaJavaObjekt
JavaJavaObjekt
...
JavaJavaObjekt
Materialisierte
Tupelfelder
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-39
Java-Repräsentation von SQL-Tupeln
z
Schnittstelle Struct definiert Java-Repräsentant des SQL-Datentyps ROW
–
–
–
z
SQL-Tupelwert wird mit der Methode getObject gelesen und implizit in
ein Struct-Objekt umgewandelt
–
z
Objekt der Klasse Struct repräsentiert einen logischen Zeiger (Lokator) auf
einen SQL-Tupelwert
Objekt enthält jedoch nicht die Feldwerte des SQL-Tupels
Feldwerte müssen mit Methoden der Klasse Struct materialisiert explizit
werden, wenn dies gewünscht ist
Genauer gesagt wird der logische Zeiger auf den SQL-Tupelwert im StructObjekt aufgebaut
Schreiben eines struct-Objekts erfolgt mit der Methode setObject
–
wandelt implizit das Struct-Objekt in einen SQL-Tupelwert um
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-40
Methoden zum Verarbeiten von SQL-Tupeln
Methoden
Object
ResultSet.getObject(int pos)
Object
ResultSet.getObject(String name)
Object
CallableStatement.getObject(int pos)
Object
CallableStatement.getObject(String name)
Object[]
Struct.getAttributes()
Struct.getAttributes()
Object[]
Struct.getAttributes(Map abbildung)
abbildung)
String
Struct.getBaseTypeName()
Struct.getBaseTypeName()
PreparedStatement.setObject(int pos, Object o)
void
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-41
Methoden der Schnittstelle Struct
z
getAttributes bildet ein Struct-Objekt auf ein Array von Java-Objekten ab,
wobei jedes Objekt ein Feld (Attribut) des SQL-Tupeltyps darstellt
–
–
z
intern nutzt diese Methode Einträge in der Typabbildungstabelle
enthält diese Tabelle keinen Eintrag für den entsprechenden SQL-Tupeltyp,
erfolgt eine Standardabbildung
getSQLTypeName liefert den Namen des SQL-Tupeltyps
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-42
Beispiel für das Verarbeiten von SQL-Tupeln (1)
String str = "SELECT Name, Anschrift FROM MitarbeiterTupeltabelle";
ResultSet rs = stmt.executeQuery(str);
while (rs.next())
{
// lies tupelwertige Spalte in ein Java-Struct-Objekt ein
Struct astruct = (Struct) rs.getObject(2);
// extrahiere Tupelfelder
Object atts [] = astruct.getAttributes();
// gib Kundenname und Wohnort aus
System.out.println(rs.getString(1) + ” wohnt in ” + atts[3]);
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-43
Beispiel für das Verarbeiten von SQL-Tupeln (2)
// erzeuge Java-Repräsentant für einen SQL-Tupelwert
Object adresse [] = new Object [5];
adresse[0] = "Über der Aar";
// Strasse
adresse[1] = 19;
// Nr
adresse[2] = 65307;
// PLZ
adresse[3] = "Bad Schwalbach";
// Ort
adresse[4] = "D";
// Land
Struct adresseStruct = new Struct(adresse);
// erzeuge vorbereitetes Anweisungsobjekt
String str = "UPDATE MitarbeiterTupeltabelle " +
"SET Anschrift = ? WHERE ID = 190697";
PreparedStatement ps = con.prepareStatement(str);
// belege tupelwertige Spalte und und führe Änderung aus
ps.setObject(1, adresseStruct);
ps.execute();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-44
Java-Repräsentation von benutzerdefinierten SQL-Typen
z
Eine Instanz eines Distinct-Typs wird durch einen Wert des Java-Typs
repräsentiert, der mit dem zugrunde liegenden SQL-Basisdatentyp
assoziiert wird
–
z
Lesen und Schreiben von Instanzen eines Distinct-Typs anhand der Methoden
des SQL-Basisdatentyps
Eine Instanz eines strukturierten Typs wird durch ein Java-Struct-Objekt
repräsentiert
–
–
Lesen und Schreiben von Instanzen eines strukturierten Typs erfolgt analog
zum Lesen und Schreiben eines SQL-Tupelwertes
Mit dieser Standardabbildung gehen allerdings die Methoden des
strukturierten Typs verloren
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-45
Beispiel für das Verarbeiten von
SQL-Distinct- und strukturierten Typwerten (1)
String str = "SELECT Name, Gehalt, Anschrift FROM Mitarbeiter";
ResultSet rs = stmt.executeQuery(str);
while (rs.next())
{
// lies Instanz eines Distinct-Typs
Double gehalt = rs.getDouble(2);
// lies Instanz eines strukturierten Typs
Struct astruct = (Struct) rs.getObject(2);
// extrahiere Objektattribute
Object atts [] = astruct.getAttributes();
// wähle bestimmte Objektattribute (PLZ und Ort) aus
int plz = atts[2];
String ort = atts[3];
// gib Namen, Gehalt, PLZ und Ort aus
System.out.println(rs.getString(1) + " verdient " + gehalt +
" und wohnt in " + plz + " " + ort);
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-46
Beispiel für das Verarbeiten von
SQL-Distinct- und strukturierten Typwerten (2)
// erzeuge Java-Repräsentant für einen Distinct-Wert
Double gehalt = 3500.85;
// erzeuge Java-Repräsentant für einen strukturierten Typwert
Object adresse [] = new Object [5];
adresse[0] = "Alexanderstrasse";
// Strasse
adresse[1] = 25;
// Nr
adresse[2] = 64289;
// PLZ
adresse[3] = "Darmstadt";
// Ort
adresse[4] = "D";
// Land
Struct adresseStruct = new Struct(adresse);
// erzeuge vorbereitetes Anweisungsobjekt
String str = "UPDATE Mitarbeiter SET Gehalt = ?, Anschrift = ? WHERE ID = 240576";
PreparedStatement ps = con.prepareStatement(str);
// belege Spalten und und führe Änderung aus
ps.setDouble(1, gehalt);
ps.setObject(2, adresseStruct);
ps.execute();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-47
Benutzerdefinierte Typabbildung
z
Mit der Standardabbildung gehen einige Besonderheiten von
benutzerdefinierten Typen verloren
–
–
z
JDBC 2 erlaubt benutzerdefinierte Typabbildungen
–
–
–
z
in SQL definierte Methoden sind nicht in der Java-Umgebung verfügbar, da die
Standardabbildung nur eine strukturelle Transformation durchführt
Navigation in komplex geschachtelten strukturierten Typen erfordert viele
Transformationen, die durch den Programmierer vorzunehmen sind
ermöglicht flexible Abbildung zwischen SQL-Datenbank und Java-Anwendung
Transformationen stehen allen Java-Anwendungen zur Verfügung
reduziert Programmieraufwand für den Anwendungsprogrammierer
Eine Java-Klasse (Java-Wrapper), die einen SQL-Datentyp repräsentieren
soll, muss die Schnittstelle java.sql.SQLData implementieren
–
SQLData definiert Methoden zur Transformation zwischen Java-Instanzen und
SQL-Instanzen von strukturierten Typen
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-48
Methoden der Schnittstelle SQL-Data
z
Austausch von Daten zwischen einer SQL-Datenbank und einem JDBCProgramm erfolgt über Datenströme
Methoden
String
SQLData.getSQLTypeName()
SQLData.getSQLTypeName()
void
SQLData.readSQL(SQLInput strom,
strom, String typname)
typname)
void
SQLData.writeSQL(SQLOutput strom)
strom)
z
getSQLTypeName gibt den Namen des SQL-Datentyps aus
z
readSQL liest einen SQL-Wert aus einem Eingabedatenstrom
z
writeSQL transformiert die Attributwerte des Java-Objekts in SQL-Werte
und schreibt diese Werte in einen Ausgabedatenstrom
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-49
Methoden der Schnittstelle SQL-Input bzw. SQL-Output
z
z
SQLInput definiert readMethoden zum Lesen von
SQL-Werten aus einem
Datenstrom
SQLInputSQLInput-Methoden SQLOutputSQLOutput-Methoden
writeString(String x)
readString()
readString()
SQLOutput definiert
Methoden zum Schreiben
von SQL-Werten in einen
Datenstrom
–
–
Rückgabetyp einer readMethode entspricht dem
Parametertyp der
korrespondierenden
write-Methode
write-Methoden haben
keinen Rückgabetyp
readShort()
readShort()
writeShort(short x)
readInt()
readInt()
writeInt(int x)
readLong()
readLong()
writeLong(long x)
readFloat()
readFloat()
writeFloat(float x)
readDouble()
readDouble()
writeDouble(double x)
…
…
readBlob()
readBlob()
writeBlob(Blob x)
readClob()
readClob()
writeClob(Clob x)
readArray()
readArray()
writeArray(Array x)
readRef()
readRef()
writeRef(Ref x)
readStruct()
readStruct()
writeStruct(Struct x)
readObject()
readObject()
writeObject(Object x)
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-50
Ablauf beim Lesen eines SQL-Wertes
z
getObject initiiert den JDBC-Treiber zu folgenden
Aktionen:
–
–
–
z
z
Erzeugen eines Objektes der zugehörigen JavaKlasse
Öffnen des Eingabedatenstroms
Belegen der Attribute des Java-Objekts mit Werten
aus dem Eingabedatenstrom
Attribute werden in der Reihenfolge eingelesen,
wie sie im SQL-Datentyp definiert wurden
getObject(i)
SQLData
readSQL(strom, typ)
SQLInput
readXXX()
Bei geschachtelten Datentypen wird ein Attribut
vollständig vor dem anderen gelesen
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-51
Ablauf beim Schreiben eines SQL-Wertes
z
setObject initiiert den JDBC-Treiber zu folgenden
Aktionen:
–
–
z
Öffnen des Ausgabedatenstrom
Schreiben der Attributwerte des Java-Objekts auf
den Ausgabedatenstrom
Attributwerte des Java-Objekts werden in der
Reihenfolge auf den Ausgabedatenstrom
geschrieben, wie sie in der Klassendefinition
aufgelistet wurden
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
setObject(i, wert)
SQLData
writeSQL(strom)
SQLOutput
writeXXX(spalte)
5-52
Implementierung eines Java-Wrappers für einen
strukturierten SQL-Typ
// SQLDefinition:
// CREATE TYPE AdresseTyp
// AS (...)
// NOT FINAL;
public void readSQL(SQLInput strom,
String typname)
throws SQLException
{
sqlTypname = typname;
strasse = strom.readString();
nr = strom.readInt();
plz = strom.readInt();
ort = strom.readString();
land = strom.readString();
}
import java.sql.*
public class Adresse implements SQLData
{
protected String sqlTypname;
public String strasse;
public int nr;
public int plz;
public String ort;
public String land;
public void writeSQL(SQLOutput strom)
throws SQLException
{
strom.writeString(strasse);
strom.writeInt(nr);
strom.writeInt(plz);
strom.writeString(ort);
strom.writeString(land);
}
public String getSQLTypeName()
{
return "AdresseTyp"
}
// weiter auf der rechten Spalte
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-53
Verwenden eines Java-Wrappers
für einen strukturierten SQL-Typ
// registriere benutzerdefinierte Typabbildung
java.util.Map map = con.getTypeMap();
map.put("AdresseTyp", Class.forName("Adresse"));
// erzeuge und führe eine SQLAnfrage aus
Statement stmt = con.createStatement();
String str = "SELECT Anschrift " +
"FROM Kunde " +
"WHERE KNr = 170470";
ResultSet rs = stmt.executeQuery(str);
rs.next();
// lies die objektwertige Spalte
Adresse a = (Adresse) rs.getObject(1);
// lies und gib ausgewählte Objektattribute aus
System.out.println( a.strasse + " " + a.nr + ", " +
a.plz + " " + a.ort);
// erzeuge vorbereitetes Anweisungsobjekt
str = "UPDATE Kunde " +
"SET Anschrift = ? " +
"WHERE KNr = 170470";
PreparedStatement ps =
con.prepareStatement(str);
// setze Attributwerte des Adresse-Objekts
a.strasse = "Editharing";
a.nr = 31;
a.plz = 39108;
a.ort = "Magdeburg";
a.land = "D";
// belege Spalte und führe Änderung aus
ps.setObject(1, a);
ps.executeUpdate();
// weiter auf der rechten Spalte
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-54
Implementierung eines Java-Wrappers
für einen SQL-Distinct-Typ
// SQLDefinition:
// CREATE TYPE Franken
// AS NUMERIC(12,2) FINAL;
public void readSQL(SQLInput strom,
String typname)
throws SQLException
{
sqlTypname = typname;
betrag = strom.readBigDecimal();
}
import java.sql.*
import java.math.*
public class Franken implements SQLData
{
protected String sqlTypname;
public BigDecimal betrag;
public void writeSQL(SQLOutput strom)
throws SQLException
{
strom.writeBigDecimal(betrag);
}
public String getSQLTypeName()
{
return "Franken"
}
public String getKuerzel()
{
return "SFR";
}
// weiter auf der rechten Spalte
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-55
Verwenden eines Java-Wrappers
für einen SQL-Distinct-Typ
// registriere benutzerdefinierte Typabbildung
java.util.Map map = con.getTypeMap();
map.put("Franken", Class.forName("Franken"));
// erzeuge und führe eine SQLAnfrage aus
Statement stmt = con.createStatement();
String str = "SELECT Name, Gehalt " +
"FROM Mitarbeiter " +
"WHERE ID = 160139";
ResultSet rs = stmt.executeQuery(str);
rs.next();
// lies Distinct-Wert
Franken f = (Franken) rs.getObject(2);
// erzeuge vorbereitetes Anweisungsobjekt
str = "UPDATE Mitarbeiter " +
"SET Gehalt = ? " +
"WHERE ID = 160139";
PreparedStatement ps =
con.prepareStatement(str);
// setze Attributwerte des Adresse-Objekts
f.betrag = f.betrag + 100;
// belege Spalte und führe Änderung aus
ps.setObject(1, f);
ps.executeUpdate();
// gib Distinct-Wert aus
System.out.println( rs.getObject(1) + " verdient " +
f.betrag + " " + f.getKuerzel());
// weiter auf der rechten Spalte
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-56
Implementierung eines Java-Wrappers
für einen SQL-Subtyp
// SQLDefinition:
// CREATE TYPE CHAdresseTyp
// UNDER AdresseTyp
// AS (Kanton VARCHAR(25))
// NOT FINAL;
public void readSQL(SQLInput strom,
String typname)
throws SQLException
{
sqlTypname = typname;
super.readSQL(strom, typname);
kanton = strom.readString();
}
import java.sql.*
public class CHAdresse extends Adresse
{
public String kanton;
public String getSQLTypeName()
{
return "CHAdresseTyp"
}
public void writeSQL(SQLOutput strom)
throws SQLException
{
super.writeSQL(strom);
strom.writeString(kanton);
}
}
// weiter auf der rechten Spalte
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-57
Verwenden eines Java-Wrappers
für einen SQL-Subtyp
// registriere benutzerdefinierte Typabbildung
java.util.Map map = con.getTypeMap();
map.put("AdresseTyp", Class.forName("Adresse"));
map.put("CHAdresseTyp", Class.forName("CHAdresse"));
// erzeuge und führe eine SQLAnfrage aus
Statement stmt = con.createStatement();
String str = "SELECT Name, Anschrift FROM Mitarbeiter WHERE ID = 100344";
ResultSet rs = stmt.executeQuery(str);
rs.next();
// lies die objektwertige Spalte
CHAdresse a = (CHAdresse) rs.getObject(2);
// lies und gib ausgewählte Objektattribute aus
System.out.println( rs.getObject(1) + " wohnt in " + a.ort + " im Kanton " + a.kanton);
// weiter auf der rechten Spalte
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-58
Generierung von Java-Wrappern
z
Generierung von Java-Wrappern durch Tools
–
–
z
Typischerweise gibt der Programmierer den Namen des benutzerdefinierten
SQL-Datentyps und den Namen der korrespondierenden Java-Klasse an
Optional können meist auch die Namen der Attribute und Methoden
umbenannt werden
Tools nutzen diese Angaben, um die Methoden getSQLTypname, readSQL
und writeSQL zu generieren
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-59
JPublisher Automatische Generierung von Java-Wrappern
z
Oracle-spezifische Konversion zwischen SQL- und Java-Typen
–
Für alle Typen werden Konstruktoren und weitere Methoden generiert, z.B.
„ Objekttypen: getXXX() und setXXX()-Methoden für alle Attribute XXX
„ Referenztypen: getValue() und setValue()-Methoden
„ Kollektionstypen: getArray() und setArray()-Methoden, getElement() und
setElement()-Methoden
// types.in : Input-Datei für JPublisher
// TYPE SQL-Typ AS Java-Typ
TYPE TelefonArrayTyp AS TelefonArrayTyp
TYPE AdresseTyp AS AdresseTyp
TYPE TeilTyp AS TeilTyp
JPublisher
TelefonArrayTyp.java
AdresseTyp.sqlj
AdresseTypRef.java
TeilTyp.sqlj
TeilTeilRef.java
Aufruf des JPublishers: jpub -input=types.in -user=scott/tiger
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-60
SQLJ
z
Standardisierte Java-DB-Schnittstelle
z
Spezifikationen
z
–
Part 0: Embedded SQL für Java
„ Statische Einbettung von SQL-Anweisungen in Java-Quelltext
–
Part 1: Java Stored Procedures
„ Im DB-Server gespeicherte Java-Prozeduren & Java-Funktionen
–
Part 2: Java-Klassen für benutzerdefinierte SQL-Datentypen
„ Verwendung von Java-Klassen als SQL-Datentypen
SQLJ ist vollständig in den SQL-Standard übernommen worden
–
–
SQLJ Part 0 als SQL Part 10: Object Language Bindings (SQL/OLB)
SQLJ Part 1 und 2 als SQL Part 13: SQL Routines and Types Using the Java
Programming Language (SQL/JRT)
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-61
Embedded SQL für Java- Überblick
z
z
Vorübersetzung des um SQLSQLAnweisungen erweiterten JavaJavaQuelltextes in „echten“ JavaJava-Code
durch Translator sqlj
Java-Quelltext mit
eingebetteten SQL-Anweisungen
SQLJSQLJ-Translator
Überprüfung der SQLSQLAnweisungen
–
–
–
SQLJProfil
korrekte Syntax
Übereinstimmung der
Anweisungen mit DB-Schema
Typkompatibilität der für den
Datenaustausch genutzten
Variablen
z
Customizing von Profilen
z
Nutzung von JDBCJDBC-Treibern
Java-Quelltext mit
JDBC-Aufrufen
Customizer
angepasstes
Profil
SyntaxSyntax-Check
DB
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
JavaJava-Compiler
Java
Byte-Code
SQLJLaufzeitsystem
JDBC
5-62
Architektur von SQLJ Part 0
// Datei: Kunden.sqlj (Implementierung eines SQLJProgramms)
Vorübersetzen des SQLJ-Programms
> sqlj Kunden.sqlj
import java.sql.*;
import sqlj.runtime.*;
Kunden.java
#sql iterator KundenIter(int KNr, String Name);
public class Kunden
{
public static void main(String argv[])
{
... // lade passenden Treiber und stelle DB-Verbindung her
Übersetzen des Java-Programms
> javac Kunden.java
Kunden.class
KundenIter kunde;
Starten des Java-Programms
> java Kunden
#sql kunde = { SELECT KNr, Name FROM Kunde };
while (kunde.next())
System.out.println(kunde.KNr() + ", " + kunde.Name());
Tabelle
Kunde
kunde.close();
}
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-63
SQLJ-Anweisungen
z
SQL-Anweisungen
–
–
–
–
z
QL-, DML- und DDL-Anweisungen
Prozeduraufrufe
Funktionsaufrufe
Aufruf unbenannter SQL-Blöcke
#sql { Anweisung };
#sql { CALL Prozedur(Param) };
#sql r = { VALUES(Funktion(Param)) };
#sql { BEGIN ... END };
Klassendefinitionen für
–
–
Iteratoren
Kontexte
#sql iterator IteratorKlasse(Typdefinitionsliste);
#sql context MyContext;
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-64
Host-Variablen
z
Variablen einer Host-Sprache (hier Java), die in SQL-Anweisungen
auftreten können
z
Verwendung: Austausch von Daten zwischen Host-Sprache und SQL
z
Zugriff auf Host-Variablen in SQLJ-Anweisungen mittels
Doppelpunktnotation :variable
z
Beispiel:
String kname;
#sql { SELECT Name INTO :kname FROM Kunde WHERE KNr = 2322 };
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-65
Iteratoren
z
Java-Objekte, die das Cursor-Konzept implementieren
z
Formen:
–
Benannte Iteratoren
#sql iterator KundeIter(int KNr, String Name);
„
„
–
Spaltenzugriff über Accessor-Methode mit dem Spaltennamen
Iteration mittels Methode next()
Positionsiteratoren
#sql iterator KundePosIter(String);
„
„
Spaltenzugriff über Position in der Anweisung
Iteration mittels FETCH...INTO-Anweisung
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-66
Benannte Iteratoren - Beispiel
// Deklaration eines benannten Iterators
#sql iterator KundeIter(int KNr, String Name);
// Definition eines Iteratorobjekts
KundeIter kunden;
// Ausführung einer SQL-Anweisung; Population des Iterators
#sql kunden = { SELECT KNr, Name FROM Kunde WHERE Name LIKE 'C%' };
// Iteration durch die Ergebnismenge; Spaltenzugriff mittels Accessor-Methoden
while (kunden.next()) {
System.out.println(kunden.KNr() + " " + kunden.Name();
}
// Iterator schliessen
kunden.close();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-67
Positionsiteratoren - Beispiel
// Deklaration eines Positionsiterators sowie einer Variablen
#sql iterator KundePosIter(String);
String kundenname;
// Definition eines Iteratorobjekts
KundePosIter kunden;
// Ausführung einer SQL-Anweisung; Population des Iterators
#sql kunden = { SELECT Name FROM Kunde WHERE Name LIKE 'C%' };
// Iteration durch die Ergebnismenge
while (true) {
#sql { FETCH :kunden INTO :kundenname };
if (kunden.endFetch()) break;
System.out.println(kundenname);
}
// Hole nächsten Datensatz
// Iterator am Ende?
// Iterator schliessen
kunden.close();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-68
Verbindungskontext
z
Jede SQL-Anweisung wird mit einem Verbindungskontext assoziiert
–
Verbindung zur einer bestimmten DB mittels expliziten Verbindungskontext
#sql context KundeKontext;
String url = "jdbc:subprotocol:datasource";
String user = "scott";
String passwd = "tiger";
KundeKontext ctx = new KundeKontext(url, user, passwd, false)
–
Ausführung einer SQL-Anweisung in einem explizitem Verbindungskontext
#sql [ctx] { SQL-Anweisung };
–
Defaultkontext
ConnectionContext.getDefaultContext()
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-69
Ausführungskontext
z
Jede SQL-Anweisung wird in einem Ausführungskontext ausgeführt
–
Definition eines expliziten Ausfürhtungskontextes
ExecutionContext execCtx = new ExecutionContext()
–
Ausführung einer SQL-Anweisung in einem explizitem Verbindungskontext
#sql [execCtx] { SQL-Anweisung };
–
Defaultkontext
ConnectionContext.getExecutionContext()
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-70
Verbindungsaufbau in Oracle
z
Oracle stellt Connect-Methode bereit, die eine DB-Verbindung und einen
Default-Kontext aufbaut
–
Entspricht etwa
Connection con = DriverManager.getConnection(url, user, passwd);
DefaultContext ctx = new DefaultContext(con);
DefaultContext.setDefaultContext(ctx);
–
Aufruf der Connect-Methode
Oracle.connect(url, user, passwd);
–
Alternativer Aufruf (Verbindungsparameter in connection.properties definiert)
Oracle.connect(JavaKlasse.class, "connection.properties");
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-71
SQLJ - Beispiel (Objekt- & Arraybehandlung in Oracle)
import java.sql.SQLException;
import oracle.sqlj.runtime.Oracle; // Package für Oracle SQLJ Support
// Benannter Iterator
#sql iterator KundenIter(String Name, AdresseTyp Anschrift, TelefonArrayTyp Telefone);
class Kunden {
public static void main (String args []) throws SQLException {
// Stelle DB-Verbindung her: URL, USER und PASSWD aus Datei connect.properties
Oracle.connect(Kunden.class, "connect.properties");
// Erzeuge Iterator, führe SQL-Anweisung aus & iteriere durch die Ergebnismenge
KundenIter kunden;
#sql kunden = { SELECT Name, Anschrift, Telefone FROM Kunde };
}
}
while (kunden.next()) {
AdresseTyp a = kunden.Anschrift();
System.out.println("Kundenname : " + kunden.Name());
System.out.println("Wohnort
: " + a.getOrt() + ", " + a.getLand());
System.out.println("Telefon
: " + kunden.Telefone().getArray()[0]);
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-72
Vergleich
z
JDBC:
–
–
–
–
z
Call-Level-Schnittstelle
Dynamisches SQL
Fehlererkennung zur Laufzeit
Hohe Flexibilität
// JDBC
int n;
Statement stmt = con.prepareStatement
(“INSERT INTO Tabelle VALUES (?)”);
stmt.setInt(1,n);
stmt.execute ();
stmt.close();
SQLJ:
–
–
–
–
Embedded-SQL-Lösung
Statisches SQL
Fehlererkennung zur Compile-Zeit
Kompakte Notation
// SQLJ
int n;
#sql{INSERT INTO Tabelle VALUES (:n)};
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-73
SQLJ / JDBC - Interoperation
z
Innerhalb einer Anwendung können SQLJ- und JDBC-Anweisungen
interoperieren
–
Erzeugen eines SQLJ-Iterators aus einem JDBC-Resultset
ResultSet rs= ...;
#sql iterator iter { ... };
#sql iter = { CAST :rs };
–
Erzeugen eines JDBC-Resultsets aus einem SQLJ-Iterator
#sql iterator iter { ... };
#sql iter = { ... };
ResultSet rs= iter.getResultSet();
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-74
Java im DB-Server
z
Java-VM als Teil des DBMS
–
–
z
Plattformneutrale, sichere Umgebung zur Ausführung prozeduraler
Anweisungen
Erweiterung des DBMS (Java Prozeduren, Funktionen & Typen)
SQLJ
–
Part 1: Java-Methoden als externe Prozeduren & Funktionen
„ im DB-Server gespeichert und ausgeführt
–
Part 2: Java-Klassen als externe SQL-Datentypen
„ Abbildung auf strukturierte Typen
–
Ablauf:
„ Implementierung → Installation → Registrierung → Nutzung
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-75
Java-Routinen
z
Vorteile
–
–
–
–
Reduzierung der
Netzwerkbelastung
PerformanceVerbesserung
Zentrale Verwaltung
„ Sicherheit
„ Backup
„ Recovery
„ Administration
Unabhängigkeit vom
Client-System
Anwendung
...
Anwendung
CALL Java-Prozedur
...
Anwendung
...
CALL Java-Prozedur
...
...
CALL Java-Prozedur
...
DBDB-Client
DB
Java-VM
Java-Prozedur
DBDB-Server
Methode
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-76
Architektur von SQLJ Part 1
// Datei: Routines.java
// Implementierung einer statischen Java-Methode
import java.sql.*;
Übersetzen des Java-Programms
> javac Routines.java
Erzeugen einer JARDatei
public class Routines
> jar cf routines.jar Routines.class
{
public static double Gehalt(int mnr)
{
routines.jar
double res = 0;
String str = "SELECT 12*Gehalt " +
"FROM Mitarbeiter " +
"WHERE MNr = ?";
CALL sqlj.install jar('file:~/routines.jar', 'J1_jar', 0);
String url = "jdbc:default:connection";
// Installation der JAR-Datei in der Datenbank
Connection con = DriverManager.getConnection(url);
PreparedStatement stmt = con.prepareStatement(str);
stmt.setInt(1, mnr);
ResultSet rs = stmt.executeQuery();
// Registrieren der Java-Methode
if (rs.next()) res = rs.getDouble(1);
// als externe Funktion
rs.close();
stmt.close();
routines.jar
CREATE FUNCTION Jahresgehalt(mnr INT)
con.close();
RETURNS DOUBLE
return res;
READS SQL DATA
Function
}
EXTERNAL NAME 'J1_jar:Routines.Gehalt(int)'
Gehalt
}
LANGUAGE JAVA
PARAMETER STYLE JAVA;
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-77
Implementierung & Installation von Java Routinen
z
Implementierung
–
–
z
als statische Methode einer Klasse
DB-Zugriff über JDBC oder SQLJ
„ Default-Verbindung zur Datenbank
„ JDBC erfordert eine explizite Default-Verbindung
Installation im Server als JAR-Archiv
CALL sqlj.install_jar('file:~/routines.jar', 'routines_jar', 0);
// Ersetzen bzw. Löschen eines JAR-Archivs
CALL sqlj.replace_jar('file:~/routines.jar', 'routines_jar');
CALL sqlj.remove_jar('routines_jar');
–
in Oracle spezielle Werkzeuge:
„ loadjava –user=scott/tiger –resolve routines.jar
„ dropjava –user=scott/tiger routines.jar
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-78
Oracle's "loadjava"
Java-Source-Code
(*.java)
Java-Class-Dateien
(*.class)
JAR-Archive
(*.jar)
loadjava
Oracle-DB
JavaCompiler
JavaSourcen
JavaKlassen
JavaResourcen
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-79
Registrierung & Aufruf von Java Routinen
z
Registrierung
–
Festlegung des Names, der Parameter und der Zuordnung zur Java-Methode
CREATE PROCEDURE GehaltErhoehen(MNr INTEGER, Betrag DECIMAL)
EXTERNAL NAME 'routines_jar:Routines.GehaltErhoehen(int, double)'
LANGUAGE JAVA
PARAMETER STYLE JAVA;
–
z
über Deployment-Deskriptor (siehe nächste Folie)
Aufruf
–
–
–
über JDBC, SQLJ, andere API
in Anfragen bzw. DML-Operationen
durch Trigger
// Aufruf einer Java-Prozedur ist
// nicht unterscheidbar von einem
// Aufruf einer SQL-Prozedur
CALL Gehalt(3443, 1250.50);
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-80
Registrierung über Deployment-Deskriptoren
z
Deployment-Deskriptor
–
–
Textdatei mit SQL-Anweisungen, die beim Installieren bzw. Entfernen eines
JAR-Archivs ausgeführt werden
Zusammen mit den Klassendateien im JAR-Archiv gespeichert
SQLActions[] = {
"BEGIN INSTALL
CREATE PROCEDURE GehaltErhoehen(MNr INTEGER, Betrag DECIMAL)
EXTERNAL NAME 'routines_jar:Routines.GehaltErhoehen(int, double)'
LANGUAGE JAVA
PARAMETER STYLE JAVA;
END INSTALL",
"BEGIN REMOVE
DROP PROCEDURE GehaltErhoehen(INTEGER, DECIMAL);
END REMOVE"
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-81
Java-Datentypen
z
Verwendung von Java-Klassen als SQL-Datentypen
–
–
z
Installation von Java-Klassen im DB-Server
Unterstützung in Sybase, Informix, Oracle
Abbildung auf SQL-Datentypen
–
–
–
Strukturierte Typen mit Attributen und Methoden
Statische Java-Attribute auf statische Methoden des strukturierten Typs
abbildbar (notwendig, weil SQL keine statischen Attribute unterstützt)
Mehrere SQL-Repräsentationen (strukturierte Typen) einer Java-Klasse möglich
„ Attribute und Methoden ausblenden bzw. umbenennen
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-82
Architektur von SQLJ Part 2
// Datei: Adresse.java
// Implementierung einer Java-Klasse
import java.sql.*
public class Adresse implements java.sql.SQLData
{
protected String sqlTypname;
public String Ort;
public int PLZ;
public int Nr;
public String Strasse;
public String Land;
public Adresse() { } ... // + SQLData-Methoden
}
Übersetzen des Java-Programms
> javac Adresse.java
Erzeugen einer JARDatei
> jar cf adresse.jar Adresse.class
adresse.jar
CALL sqlj.install jar('file:~/adresse.jar', 'adr_jar', 0);
// Installation der JAR-Datei in der Datenbank
// Registrieren der Java-Klasse als externer Datentyp
CREATE TYPE AdresseTyp
EXTERNAL NAME ’adr_jar:Adresse’
LANGUAGE JAVA AS
(
Strasse VARCHAR(30) EXTERNAL NAME 'Strasse',
Nr
INTEGER
EXTERNAL NAME 'Nr',
PLZ
INTEGER
EXTERNAL NAME 'PLZ',
Ort
VARCHAR(40) EXTERNAL NAME 'Ort',
Land
VARCHAR(25) EXTERNAL NAME 'Land'
) NOT FINAL
CONSTRUCTOR METHOD AdresseTyp() RETURNS AdresseTyp
EXTERNAL NAME 'Adresse() return Adresse';
adresse.jar
Type
AdresseTyp
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-83
Implementierung von Java-Datentypen
z
Klasse mit Schnittstelle java.sql.SQLData oder java.io.Serializable
z
Attribute zur Repräsentation von SQLSQL-Daten als public definiert
z
Zur Ausgabe: (optionale) Definition der Methode toString
z
Beispiel:
import java.sql.*
public class Adresse implements java.sql.SQLData
{
protected String sqlTypname;
public String Strasse;
public int Nr;
public int PLZ;
public String Ort;
public String Land;
public Adresse() { Strasse = Ort = Land = ""; Nr = PLZ = 0; }
public String Wohnort() { return PLZ + " " + Ort; }
... // SQLData-Methoden wie auf Folie 53
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-84
Installation & Registrierung von Java-Datentypen
z
Installation von Java-Klassen im DB-Server als JAR-Archiv
CALL sqlj.install_jar('file:~/adresse.jar', 'adr_jar', 0);
z
Registrierung über
–
erweitere Form von CREATE TYPE (Abbildung der Klasse: Attribute & Methoden)
CREATE TYPE AdresseTyp
EXTERNAL NAME 'adr_jar:Adresse'
LANGUAGE JAVA
AS
(... PLZ INTEGER EXTERNAL NAME 'PLZ' ... )
NOT FINAL
CONSTRUCTOR METHOD AdresseTyp() RETURNS AdresseTyp SELF AS RESULT
EXTERNAL NAME 'Adresse() return Adresse',
...;
–
vordefinierte Prozeduren (wie in Informix)
EXECUTE PROCEDURE sqlj.setUDTExtName(SQL-Typname, Java-Klassenname);
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-85
Nutzung von Java-Datentypen
z
Verwendung des Java-Datentyps z. B. als Spaltentyp
CREATE TABLE Person (
Name
VARCHAR(30),
Anschrift
AdresseTyp
);
z
Initialisierung durch Konstruktor
INSERT INTO Person (Name, Anschrift) VALUES ('Joe', NEW AdresseTyp());
z
Zugriff auf Attribute und Methoden
SELECT Anschrift.Land, Anschrift.Wohnort FROM Person;
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-86
Implementierung von Java-Subtypen
import java.sql.*
public class CHAdresse extends Adresse
{
// Objektattribute
public String Kanton;
// Konstruktoren
public CHAdresse() {
super.Adresse();
kanton = "";
}
public CHAdresse(String s, int n, int p, String o, String l, String k) {
super.Adresse(s, n, p, o, l);
kanton = k;
}
// lesende Methode
public String CHWohnort() { return super.Wohnort() + "-"+ Kanton; }
... // SQLData-Methoden wie auf Folie 57
}
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-87
Registrierung von Java-Subtypen
CREATE TYPE CHAdresseTyp UNDER AdresseTyp
EXTERNAL NAME 'adr_jar:CHAdresse'
LANGUAGE JAVA
AS
( -- Attributzuordnungen
Kanton VARCHAR(30) EXTERNAL NAME 'kanton'
)
NOT FINAL
-- Methodenzuordnungen
CONSTRUCTOR METHOD CHAdresseTyp()
RETURNS CHAdresseTyp SELF AS RESULT
EXTERNAL NAME 'CHAdresse() return CHAdresse',
CONSTRUCTOR METHOD CHAdresseTyp( s VARCHAR(30), n INTEGER, p INTEGER,
o VARCHAR(40), l VARCHAR(25), k VARCHAR(30))
RETURNS CHAdresseTyp SELF AS RESULT
EXTERNAL NAME 'CHAdresse(String, int, int, String, String, String) return CHAdresse',
METHOD CHWohnort()
RETURNS VARCHAR(45)
EXTERNAL NAME 'CHWohnort() return String';
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-88
Java-Klassenhierarchien vs. SQL-Typhierarchien
z
Keine überschreibenden externen Java-Methoden erlaubt
z
Alle Typen einer Hierarchie müssen externe Java-Datentypen sein, wenn
mindestens eine davon ein externer Java-Datentyp ist
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-89
Zusammenfassung
z
JDBC und SQLJ sind Java-SQL-Schnittstellen
–
–
z
Vorteile objektrelationaler Datenbanken kommen bei der
Anwendungsentwicklung erst bei Nutzung einer objektorientierten
Programmiersprache richtig zur Geltung
–
–
–
z
unterstützen objektrelationale Erweiterungen
werden von den meisten kommerziellen DBMS angeboten (aber nicht in
vollem Umfang)
Wichtig: nicht nur die Struktur, sondern auch das Verhalten (Methoden) der
strukturierten Typen muss abgebildet werden
transparenter Aufruf von in der Datenbank gespeicherten Methoden im
Anwendungsprogramm
transparentes Verfolgen von Referenzen
Tools ermöglichen die Abbildung objektrelationaler Erweiterungen
–
–
aktuelle Tools haben noch viel Potential für Verbesserungen
aktuelle DBMS bieten nicht für alle OR-Erweiterungen Default-Abbildungen an
Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2004/2005 (Dr. Can Türker)
5-90
Herunterladen