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 2003/2004 (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 2003/2004 (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 2003/2004 (Dr. Can Türker) 5-4 Java und Datenbankanwendungen Benutzerschnittstelle CORBA, HTTP, ... Benutzerschnittstelle DB-Client Anwendungslogik DB-Schnittstelle Anwendungslogik JDBC, SQLJ DB-Schnittstelle DBMS-Protokoll DB-Server DB-Client AnwendungsServer DBMS-Protokoll DB DB DB-Server Benutzerdefinierte Prozeduren, Funktionen & Datentypen in Java Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (Dr. Can Türker) 5-8 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 2003/2004 (Dr. Can Türker) 5-9 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 2003/2004 (Dr. Can Türker) 5-10 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 2003/2004 (Dr. Can Türker) 5-11 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 2003/2004 (Dr. Can Türker) 5-12 Typabbildung von Java nach SQL Typabbildung von SQL nach Java SQL get-Methode Java-Typ Java-Typ set-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 SQL:1999 bzw SQL:2003 wird später vorgestellt Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) 5-13 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 2003/2004 (Dr. Can Türker) 5-14 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 2003/2004 (Dr. Can Türker) 5-15 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 2003/2004 (Dr. Can Türker) 5-16 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 2003/2004 (Dr. Can Türker) 5-17 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 2003/2004 (Dr. Can Türker) 5-18 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 2003/2004 (Dr. Can Türker) 5-19 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 Transationen 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 2003/2004 (Dr. Can Türker) 5-20 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_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 2003/2004 (Dr. Can Türker) 5-21 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 Erzeuge und führe SQL -Anweisungoracle.jdbc.driver.OracleDriver()); aus Erzeuge und führe SQL-Anweisung aus Connection con = DriverManager.getConnection("jdbc:oracle:oci8:@", "scott", "tiger"); Statement stmt ==con. createStatement( , createStatement ResultSet.TYPE_SCROLL_SENSITIVE // Iteriere durch die Ergebnismenge Statement stmt con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ////Iteriere durch Ergebnismenge Erzeuge und die führe SQL-Anweisung aus & iteriere durch die Ergebnismenge ResultSet.CONCUR_UPDATABLE ); while ( rs. next ()) { ResultSet.CONCUR_UPDATABLE); while (rs.next()) { Statement stmt =executeQuery con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet rsrs= stmt. ("SELECT Name, Kreidit System . out . println ("Kundenname getString (1));FROM ResultSet = stmt.executeQuery("SELECT Name, Kreidit FROMKunde"); Kunde"); System.out.println("Kundenname : : ""++rs. rs.getString(1)); ResultSet.CONCUR_UPDATABLE); System .outrs .println ("Bisheriger Kreditrahmen: ""++rs. getFloat (2));Kunde"); System.out.println("Bisheriger Kreditrahmen: rs.getFloat(2)); ResultSet = stmt.executeQuery("SELECT Name, Kredit FROM rs. updateFloat (2, {rs. getFloat(2) ++100.0f); rs.updateFloat(2, rs.getFloat(2) 100.0f);////Attribut Attributdes desaktuellen aktuellenTupels Tupelsändern ändern while (rs.next()) rs. updateRow(); ////Änderung inindie rs.updateRow(); Änderung dieDatenbank Datenbankübernehmen übernehmen 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 2003/2004 (Dr. Can Türker) 5-22 ResultSet-Methoden zum Scrollen Methoden Cursor-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 2003/2004 (Dr. Can Türker) 5-23 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 2003/2004 (Dr. Can Türker) 5-24 Typabbildung von Java nach SQL Typabbildung von SQL nach Java SQL BLOB CLOB ARRAY ROW REF Distinct-Typ Strukturierter Typ get-Methode Java-Typ Java-Typ set-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 Distinct-Typ Strukturierter Typ X ist der Basisdatentyp, der einem Distinct-Typ zugrunde liegt! Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) 5-25 JDBC - Beispiel (in Oracle) import java.sql.*; import java.util.*; class Kunden { ////Lade Oracle JDBC Treiber und stelle Verbindung zur ORDB Ladestatic Oracle JDBC Treiber und stelle Verbindung zurDatenbank Datenbank ORDBher her public void main (String args []) throws SQLException { DriverManager .registerDriver(new oracle.jdbc.driver. OracleDriver()); DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Lade Oracle JDBC Treiber und stelle Verbindung zur Datenbank ORDB her Connection con .getConnection("jdbc:oracle:oci8:@", ""scott", scott", ""tiger"); tiger"); Connection con==DriverManager DriverManager.getConnection("jdbc:oracle:oci8:@", DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); con = DriverManager.getConnection("jdbc:oracle:oci8:@", "scott", "tiger"); ////Connection Erzeuge und führe SQL Anweisung aus Erzeuge und führe SQL-Anweisung aus // Erzeuge und führe SQL-Anweisung aus & iteriere durch die Ergebnismenge Statement stmt ==con. createStatement(); // Iteriere durch die Ergebnismenge Statement stmt con.createStatement(); //Statement Iteriere durch die Ergebnismenge stmt =executeQuery con.createStatement(); ResultSet rs = stmt. ("SELECT Name, Anschrift, Telefone FROM Kunde"); while (rs.next()) { ResultSet rs = stmt.executeQuery("SELECT Name, Anschrift, Telefone FROM while (rs.next()) { ResultSet rs = stmt.executeQuery("SELECT Name, Anschrift, Telefone FROMKunde"); Kunde"); Struct a = (Struct) rs.getObject(2); Struct(rs.next()) a = (Struct) while { rs.getObject(2); Object [][]==a.getAttributes(); Object attrs a.getAttributes(); Structattrs a = (Struct) rs.getObject(2); Array tt==attrs rs.getArray(3); Array rs.getArray(3); Object []Ergebnismenge = a.getAttributes(); //// Schliesse die Schliesse die Ergebnismenge System.out.println("Kundenname: ""++rs.getString(1)); System.out.println("Kundenname: rs.getString(1)); Array t = rs.getArray(3); rs. close (); rs.close(); System.out.println("Wohnort: ""++attrs[3] ++",",""++attrs[4]); System.out.println("Wohnort: attrs[3] attrs[4]); System.out.println("Kundenname : " + rs.getString(1)); System .out.println("Telefon: ""++(String)((Object[])t. ())[0].toString()); System.out.println("Telefon: (String)((Object[])t.getArray())[0].toString()); System.out.println("Wohnort : " + attrs[3] + ",getArray " + attrs[4]); // Schliesse die Anweisung Schliesse die Anweisung }// } System.out.println("Telefon : " +(String)((Object[])t.getArray())[0].toString()); stmt. close(); stmt.close(); } stmt.close(); con.close(); // Schliessen aller Resourcen ////rs.close(); Schliesse Schliessedie dieVerbindung Verbindung } close(); con. con.close(); } Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) 5-26 Illustration der Abbildung von SQL-Arrays nach Java ResultSet getArray(i) SQL-Arraywert Java-ArrayObjekt Java-Array-Lokator (Referenz auf SQL-Arraywert) getArray() JavaObjekt JavaObjekt ... JavaObjekt Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) Materialisierte Array-Felder 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 2003/2004 (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() int Array.getArray(long pos, int länge) Array.getBaseType() String Array.getBaseTypeName() Object[] ResultSet Array.getResultSet() ResultSet Array.getResultSet(long pos, int länge) void PreparedStatement.setArray(int pos, Array wert) Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (Dr. Can Türker) 5-32 Illustration der Abbildung von SQL-Referenzen nach Java ResultSet getRef(i) SQL-Referenzwert Java-RefObjekt Java-Ref-Lokator (Referenz auf SQL-Referenzwert) getObject() SQL-Objektwert Java-StructObjekt Java-Struct-Lokator (Referenz auf SQL-Objektwert) getAttributes() JavaObjekt JavaObjekt ... JavaObjekt Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) Materialisierte Objektattribute 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 2003/2004 (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(Map abbildung) Ref.setObject(Object o) Ref.getBaseTypeName() PreparedStatement.setRef(int pos, Ref wert) Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (Dr. Can Türker) 5-38 Illustration der Abbildung von SQL-Tupeln nach Java ResultSet getObject(i) SQL-Tupelwert Java-StructObjekt Java-Struct-Lokator (Referenz auf SQL-Tupelwert) getAttributes() JavaObjekt JavaObjekt ... JavaObjekt Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) Materialisierte Tupelfelder 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 2003/2004 (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() Object[] Struct.getAttributes(Map abbildung) String Struct.getBaseTypeName() PreparedStatement.setObject(int pos, Object o) void Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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() void SQLData.readSQL(SQLInput strom, String typname) void SQLData.writeSQL(SQLOutput 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 2003/2004 (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 SQLInput-Methoden SQLOutput-Methoden writeString(String x) 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() writeShort(short x) readInt() writeInt(int x) readLong() writeLong(long x) readFloat() writeFloat(float x) readDouble() writeDouble(double x) … … readBlob() writeBlob(Blob x) readClob() writeClob(Clob x) readArray() writeArray(Array x) readRef() writeRef(Ref x) readStruct() writeStruct(Struct x) readObject() writeObject(Object x) Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (Dr. Can Türker) 5-60 SQLJ z Standardisierte Java-DB-Schnittstelle z Spezifikationen – Part 0: Embedded SQL für Java (ANSI-Standard; Object Language Binding) Statische Einbettung von SQL-Anweisungen in Java-Quelltext – Part 1: Java Stored Procedures (ANSI-Standard; seit September 1999) Im DB-Server gespeicherte Java-Prozeduren & Java-Funktionen – Part 2: Java-Klassen für benutzerdefinierte SQL-Datentypen Verwendung von Java-Klassen als SQL-Datentypen z Oracle, IBM, Informix, Sybase, Tandem, Sun, Microsoft stehen dahinter z 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 2003/2004 (Dr. Can Türker) 5-61 Embedded SQL für Java- Überblick z z Vorübersetzung des um SQLAnweisungen erweiterten JavaQuelltextes in „echten“ Java-Code durch Translator sqlj Java-Quelltext mit eingebetteten SQL-Anweisungen SQLJ-Translator Überprüfung der SQLAnweisungen – – – 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 JDBC-Treibern Java-Quelltext mit JDBC-Aufrufen Customizer angepasstes Profil Syntax-Check DB Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) Java-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 Routines.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; #sql kunde = { SELECT KNr, Name FROM Kunde }; Starten des Java-Programms > java Kunden while (kunde.next()) System.out.println(kunde.KNr() + ", " + kunde.Name()); kunde.close(); } Tabelle Kunde } Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 Benannter Iterator BenannterIterator Iterator #sql iterator KundenIter(String Name, AdresseTyp Anschrift, TelefonArrayTyp Telefone); ##sql sql iterator iteratorKundenIter(String KundenIter(StringName, Name,AdresseTyp AdresseTypAnschrift, Anschrift,TelefonArrayTyp TelefonArrayTypTelefone); 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 ErzeugeIterator Iterator KundenIter kunden ; führe //// eingebettete SQL -SQL-Anweisung Anweisung aus //Führe Erzeuge Iterator, KundenIter kunden; Führe eingebettete SQL-Anweisung aus aus & iteriere durch die Ergebnismenge KundenIter kunden; ##sql sql kunden =={{SELECT Name, // durch die kunden SELECT Name,Anschrift, Anschrift,Telefone TelefoneFROM FROMKunde Kunde};}; //Iteriere Iteriere durch dieErgebnismenge Ergebnismenge while kunden. ()) {{ Name, Anschrift, Telefone FROM Kunde }; while (kunden.next()) #sql (kunden =next { SELECT AdresseTyp (); AdresseTypaa==kunden.Anschrift kunden.Anschrift(); System .out.println("Kundenname : : ""++kunden.Name ()); while (kunden.next()) { System.out.println("Kundenname kunden.Name()); AdresseTyp = kunden.Anschrift(); System .outa.println ("Wohnort : : ""++a.a.getOrt() getOrt() ++",",""++a.a.getLand()); getLand()); System.out.println("Wohnort System.out.println("Kundenname : : ""++kunden.Name()); System .out.println("Telefon kunden.Telefone(). getArray()[0]); System.out.println("Telefon : +" +a.getOrt() kunden.Telefone().getArray()[0]); System.out.println("Wohnort : " + ", " + a.getLand()); }} System.out.println("Telefon : " + kunden.Telefone().getArray()[0]); } } Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 2003/2004 (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 2003/2004 (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 2003/2004 (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 ... DB-Client DB Java-VM Java-Prozedur DB-Server Methode Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (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 > jar cf routines.jar Routines.class public class Routines { 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 2003/2004 (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 Oracle8i spezielle Werkzeuge: loadjava –user=scott/tiger –resolve routines.jar dropjava –user=scott/tiger routines.jar Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) 5-78 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 2003/2004 (Dr. Can Türker) 5-79 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 2003/2004 (Dr. Can Türker) 5-80 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 2003/2004 (Dr. Can Türker) 5-81 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'; Vorlesung "Objektrelationale, erweiterbare Datenbanken" - WS 2003/2004 (Dr. Can Türker) adresse.jar Type AdresseTyp 5-82 Implementierung von Java-Datentypen z Klasse mit Schnittstelle java.sql.SQLData oder java.io.Serializable z Attribute zur Repräsentation von SQL-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 2003/2004 (Dr. Can Türker) 5-83 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 2003/2004 (Dr. Can Türker) 5-84 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 2003/2004 (Dr. Can Türker) 5-85 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 2003/2004 (Dr. Can Türker) 5-86 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 2003/2004 (Dr. Can Türker) 5-87 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 2003/2004 (Dr. Can Türker) 5-88 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 2003/2004 (Dr. Can Türker) 5-89