Kapitel 7 Java-Anbindung für objektrelationale Datenbanken Java und Datenbanken JDBC SQLJ Lesestoff Programmiersprache Java l Java ist – – – – – objektorientiert (Klassen als Abstraktionskonzept) einfach n automatisierte Speicherverwaltung n Verzicht auf Zeiger und Goto robust und sicher n strenge Typisierung n Laufzeitüberpüfung von Zugriffen interpretiert und dynamisch architekturneutral und portabel n Plattformunabhängiger Zwischencode (Bytecode) n Programme sind ohne Änderungen ablauffähig unter Windows, Unix, ... Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-2 Java und Datenbanken l Einsatz von Java – – – auf Client-Seite: n DB-Anwendungen auf Server-Seite: n DB-Erweiterungen (benutzerdefinierte Prozeduren, Funktionen & Datentypen) auf Middleware-Ebene: n Anwendungslogik (JavaBeans) l Anbindung Java - Datenbank – – JDBC (Java Database Connectivity; Call-Level-Schnittstelle) SQLJ (Embedded SQL; Java-Relational Database Technology) Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-3 Java und Datenbankanwendungen Benutzerschnittstelle DB-Client CORBA, HTTP, ... Benutzerschnittstelle DB-Client Anwendungslogik DB-Schnittstelle DBMS-Protokoll DB-Server Anwendungslogik JDBC, SQLJ DB DB-Schnittstelle AnwendungsServer DBMS-Protokoll DB DB-Server Benutzerdefinierte Prozeduren, Funktionen & Datentypen in Java Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-4 JDBC - Überblick l Datenbankzugriffsschnittstelle für Java – – – – abstrakt und datenbankneutral vergleichbar mit ODBC Low-Level-API: direkte Nutzung von SQL Java-Package java.sql l 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 2001/2002 (Dr. C. Türker) 7-5 Datenbankanbindung - Ablauf l Aufbau einer Verbindung zur Datenbank – – Angabe der Verbindungsinformationen Auswahl und dynamisches Laden des Treibers l Senden einer SQL-Anweisung – – Definition der Anweisung Belegung von Parametern l Verarbeiten der Anfrageergebnisse – – Navigation über Ergebnisrelation Zugriff auf Spalten Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) DriverManager getConnection() Connection createStatement() Statement executeQuery() ResultSet 7-6 Verbindungsaufbau l Treiber laden (2 Varianten) Class.forName("com.company.DBDriver"); Oracle oracle.jdbc.driver.OracleDriver DB2 COM.ibm.db2.jdbc.app.DB2Driver Informix com.informix.jdbc.IfxDriver DriverManager.registerDriver(new com.company.DBDriver()); l Verbindung herstellen String url = "jdbc:subprotocol:datasource"; String user = "scott"; String passwd = "tiger"; Connection con = DriverManager.getConnection(url, user, passwd); – JDBC-URL spezifiziert n Datenquelle/Datenbank n Verbindungsmechanismus (Protokoll, Server-Host und Port) Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-7 Ausführung einer DB-Anfrage bzw. DB-Änderung l Anweisungsobjekt (Statement) erzeugen Statement stmt = con.createStatement(); l Anweisung ausführen String queryStmt = "SELECT Name, Anschrift FROM Kunde"; ResultSet rset = stmt.executeQuery(queryStmt); – Klasse java.sql.Statement n Ausführung von Anfragen (SELECT) mit executeQuery n 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 2001/2002 (Dr. C. Türker) 7-8 Ergebnisverarbeitung l Navigation über Ergebnismenge (Cursor-Prinzip) while (rset.next()) { // Verarbeitung der einzelnen Tupel ... } l 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 2001/2002 (Dr. C. Türker) 7-9 Lesestoff Fehlerbehandlung l Fehlerbehandlung mittels Exception-Mechanismus l 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 2001/2002 (Dr. C. Türker) 7-10 Lesestoff Transaktionssteuerung l Methoden von Connection – – commit() rollback() l Auto-Commit-Modus – – – implizites Commit nach jeder Anweisung Transaktion besteht nur aus einer Anweisung Umschalten mittels setAutoCommit(boolean) l 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 2001/2002 (Dr. C. Türker) 7-11 Anfrageformen l Statement – – Basisklasse für alle Anweisungen Verarbeitung einfacher SQL-Anweisungen ohne Parameter l PreparedStatement – – – Kapselung einer vorkompilierten Anweisung parametrisierbar Verwendung: wiederholte Ausführung einer Anweisung (mit verschiedenen Parametern) l CallableStatement – Aufruf von gespeicherten Prozeduren mit Parametern Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-12 Vorübersetzte Anweisungen l java.sql.PreparedStatement – – Beschleunigung der Ausführung von Anweisungen durch Vorübersetzung und wiederholten Aufruf mit verschiedenen Parametersätzen l Anweisungsobjekt (PreparedStatement) erzeugen String insStmt = "INSERT INTO Kunde VALUES (?, ?)"; PreparedStatement stmt = con.prepareStatement(insStmt); Anweisungsparameter durch "?" markiert l Belegung der Parameter mittels setXXX-Methoden stmt.setString(1, "George"); stmt.setFloat(2, 4500.00); l Anweisung ausführen stmt.executeUpdate(insStmt); Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-13 Aufruf von gespeicherten Prozeduren l java.sql.CallableStatement – Aufruf von gespeicherten Prozeduren (Stored Procedures) l Anweisungsobjekt (CallableStatement) erzeugen und Parameter setzen String callStmt = "{CALL TestProc(?, ?)}"; CallableStatement stmt = con.prepareCall(callStmt); stmt.setInt(1, 42); l 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 2001/2002 (Dr. C. Türker) 7-14 Lesestoff JDBC-Interfaces ResultSet executeQuery executeUpdate Statement executeQuery executeUpdate getXXX PreparedStatement setXXX Data Types DriverManager createStatement getConnection prepareStatement Connection prepareCall getXXX CallableStatement Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-15 Lesestoff Neue Features in JDBC 2 l Core API - Bestandteil von Java 2 – – – – Scrollbare und änderbare ResultSets Batch-Updates SQL-99-Datentypen Benutzerdefinierte Typabbildung l Optional API – – – – Nutzung von Namensdiensten (JNDI) Connection Pooling Verteilte Transationen RowSets Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) // 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() 7-16 JDBC - Beispiel (in Oracle) import java.sql.*; import java.util.*; class Kunden { // Lade Oracle Verbindung zur ORDB // Ladestatic Oracle JDBC Treiberund undstelle stelle Verbindung zurDatenbank Datenbank ORDBher her public voidJDBC main Treiber (String args []) throws SQLException { DriverManager .registerDriver oracle.jdbc.driver. ()); her // Lade Oracle JDBC Treiber(new und stelle Verbindung zurOracleDriver Datenbank ORDB DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection con = DriverManager.getConnection ("jdbc:oracle:oci8:@", "scott", "tiger"); Connection "scott", "tiger"); Connectioncon con= = DriverManager.getConnection("jdbc:oracle:oci8:@", DriverManager.getConnection("jdbc:oracle:oci8:@", "scott", "tiger"); // Erzeuge und führe SQL Anweisung aus ////Erzeuge aus& iteriere durch die Ergebnismenge Erzeugeund und führe führe SQL-Anweisung SQL-Anweisung aus // Iteriere durch die Ergebnismenge Statement con. createStatement(); Statement stmt= = con.createStatement(); // Iterierestmt durch die Ergebnismenge Statement stmt = con.createStatement(); ResultSet =stmt. Anschrift, Telefone FROM Kunde"); while (rs.next()) {stmt.executeQuery("SELECT ResultSet rsrsrs= Name, Anschrift, Telefone FROM Kunde"); while (rs.next()) { executeQuery("SELECTName, ResultSet = stmt.executeQuery("SELECT Name, Anschrift, Telefone FROM Kunde"); while (rs.next()) { Struct a = (Struct) rs.getObject(2); Struct Structa a= =(Struct) (Struct) rs.getObject(2); rs.getObject(2); Object attrs [] = a.getAttributes(); Object attrs [] = a.getAttributes(); attrsdie [] Ergebnismenge = a.getAttributes(); // Schliesse //Object Schliesse die Ergebnismenge Array t = rs.getArray(3); Array rs. closet(); Array t= =rs.getArray(3); rs.getArray(3); rs.close(); System.out.println("Kundenname :+" rs.getString(1)); + rs.getString(1)); System.out.println("Kundenname: " System.out.println("Kundenname: " + rs.getString(1)); // Schliesse die Anweisung System.out.println("Wohnort : "+ attrs[3] + ", " + attrs[4]); // Schliesse die Anweisung System.out.println("Wohnort: " + attrs[3] + System.out.println("Telefon " +(String)((Object[])t.getArray())[0].toString()); stmt. close(); System.out.println("Wohnort: " + :attrs[3] +",",""+ +attrs[4]); attrs[4]); stmt.close(); } System .out.println("Telefon: ""+ getArray())[0].toString()); System.out.println("Telefon: +(String)((Object[])t. (String)((Object[])t.getArray())[0].toString()); // Schliesse die Verbindung // Schliesse die Verbindung rs.close(); stmt.close(); con.close(); // Schliessen aller Resourcen }con. }} close(); con.close(); } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-17 SQLJ l Standardisierte Java-DB-Schnittstelle l Spezifikationen – Part 0: Embedded SQL für Java (ANSI-Standard; Object Language Binding) n Statische Einbettung von SQL-Anweisungen in Java-Quelltext – Part 1: Java Stored Procedures (ANSI-Standard; seit September 1999) n Im DB-Server gespeicherte Java-Prozeduren & Java-Funktionen – Part 2: Java-Klassen für benutzerdefinierte SQL-Datentypen n Verwendung von Java-Klassen als SQL-Datentypen l Oracle, IBM, Informix, Sybase, Tandem, Sun, Microsoft stehen dahinter Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-18 Embedded SQL für Java- Überblick l Vorübersetzung des um SQLAnweisungen erweiterten JavaQuelltextes in „echten“ Java-Code durch Translator sqlj Java-Quelltext mit eingebetteten SQL-Anweisungen SQLJ-Translator SQLJ- Java-Quelltext mit JDBC-Aufrufen Profil l Überprüfung der SQL-Anweisungen – korrekte Syntax – Übereinstimmung der Anweisungen mit DB-Schema – Typkompatibilität der für den Datenaustausch genutzten Variablen Java-Compiler Java Byte-Code Customizer Syntax-Check l Nutzung von JDBC-Treibern DB SQLJLaufzeitsystem JDBC Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-19 SQLJ-Anweisungen l SQL-Anweisungen – – – – 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 }; l Klassendefinitionen für – – Iteratoren Kontexte #sql iterator IteratorKlasse(Typdefinitionsliste); #sql context MyContext; Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-20 Lesestoff Host-Variablen l Variablen einer Host-Sprache (hier Java), die in SQL-Anweisungen auftreten können l Verwendung: Austausch von Daten zwischen Host-Sprache und SQL l Zugriff auf Host-Variablen in SQLJ-Anweisungen mittels Doppelpunktnotation :variable l Beispiel: String kname; #sql { SELECT Name INTO :kname FROM Kunde WHERE KNr = 2322 }; Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-21 Iteratoren l Java-Objekte, die das Cursor-Konzept implementieren l Formen: – Benannte Iteratoren #sql iterator KundeIter(int KNr, String Name); n Spaltenzugriff über Accessor-Methode mit dem Spaltennamen n Iteration mittels Methode next() – Positionsiteratoren #sql iterator KundePosIter(String); n Spaltenzugriff über Position in der Anweisung n Iteration mittels FETCH...INTO-Anweisung Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-22 Lesestoff 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 2001/2002 (Dr. C. Türker) 7-23 Lesestoff 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 }; // Hole nächsten Datensatz if (kunden.endFetch()) break; // Iterator am Ende? System.out.println(kundenname); } // Iterator schliessen kunden.close(); Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-24 Lesestoff Verbindungskontext l 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 2001/2002 (Dr. C. Türker) 7-25 Lesestoff Ausführungskontext l 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 2001/2002 (Dr. C. Türker) 7-26 Lesestoff Verbindungsaufbau in Oracle l 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"); 7-27 Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) JPublisher - Automatische Generierung von Java-Wrappern l Oracle-spezifische Konversion zwischen SQL- und Java-Typen – Für alle Typen werden Konstruktoren und weitere Methoden generiert, z.B. n Objekttypen: getXXX() und setXXX()-Methoden für alle Attribute XXX n Referenttypen: getValue() und setValue()-Methoden n 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 2001/2002 (Dr. C. Türker) 7-28 SQLJ - Beispiel (Objekt- & Arraybehandlung in Oracle) import java.sql.SQLException; import oracle.sqlj.runtime.Oracle; // Package für Oracle SQLJ Support // Iterator // Benannter Iterator //Benannter Benannter Iterator #sql iterator KundenIter(String Name, AdresseTyp Anschrift, TelefonArrayTyp Telefone); #sql iterator elefone); #sql iterator KundenIter(StringName, Name,AdresseTyp AdresseTypAnschrift, Anschrift,TelefonArrayTyp TelefonArrayTypTTelefone); class Kunden { KundenIter(String 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 //Erzeuge ErzeugeIterator Iterator, führe eingebettete SQL-Anweisung aus & iteriere durch die Ergebnismenge // F ühre eingebettete -Anweisung aus kunden; SQL SQL-Anweisung aus //KundenIter Führe eingebettete KundenIter kunden; KundenIter kunden; // Iteriere durch dieSELECT Ergebnismenge // Iteriere durch Ergebnismenge #sql kunden = SELECT Name, Telefone FROM Kunde }; }; #sql kunden = Name, Anschrift, Telefone FROM Kunde #sql kunden ={{{die SELECT Name,Anschrift, Anschrift, Telefone FROM Kunde }; while (kunden.next()) { while next()) {{ while(kunden. (kunden.next()) AdresseTyp a = iter.Anschrift(); AdresseTyp aa= AdresseTyp =iter.Anschrift(); iter.Anschrift(); System.out.println("Kundenname iter.Name()); System . out . println ("Kundenname: ::" "+ + iter.Name()); System.out.println("Kundenname " + iter.Name()); System.out.println("Wohnort : " + a.getOrt() ++ ", "",+" + a.getLand()); System . out . println ("Wohnort : " + a. getOrt() getLand()); System.out.println("Wohnort : :" + " +iter.Telefone().getArray()[0]); a.getOrt() + ", " +a.a.getLand()); System.out.println("Telefon System.out.println("Telefon :: ""+ getArray()[0]); +iter.Telefone(). iter.Telefone().getArray()[0]); } System.out.println("Telefon }}} } 7-29 Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) Vergleich l JDBC: – – – – Call-Level-Schnittstelle Dynamisches SQL Fehlererkennung zur Laufzeit Hohe Flexibilität l SQLJ: – – – – Embedded-SQL-Lösung Statisches SQL Fehlererkennung zur Compile-Zeit Kompakte Notation Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) // JDBC int n; Statement stmt = con.prepareStatement (“INSERT INTO Tabelle VALUES (?)”); stmt.setInt(1,n); stmt.execute (); stmt.close(); // SQLJ int n; #sql{INSERT INTO Tabelle VALUES (:n)}; 7-30 SQLJ / JDBC - Interoperation l 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 2001/2002 (Dr. C. Türker) 7-31 Java im DB-Server l Java-VM als Teil des DBMS – – Plattformneutrale, sichere Umgebung zur Ausführung prozeduraler Anweisungen Erweiterung des DBMS (Java Prozeduren, Funktionen & Typen) l SQLJ – Part 1: Benutzerdefinierte Java-Prozeduren & Java-Funktionen n im DB-Server gespeichert und ausgeführt – Part 2: Benutzerdefinierte Java-Klassen als SQL-Datentypen n als Spaltentypen von Datenbankrelationen verwendbar – Ablauf: n Implementierung → Installation → Registrierung → Nutzung Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-32 Gespeicherte Prozeduren & Funktionen l Vorteile – – – – Reduzierung der Netzwerkbelastung Performance-Verbesserung Zentrale Verwaltung n Sicherheit n Backup n Recovery n Administration Unabhängigkeit vom Client-System Anwendung Anwendung ... Anwendung ... CALL Java-Prozedur ... CALL Java-Prozedur DB-Client ... CALL Java-Prozedur ... ... DB Java-VM Java-Prozedur DB-Server Methode Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-33 Gespeicherte Prozeduren & Funktionen: Ablauf l Implementierung – – – als statische Methode einer Klasse Default-Verbindung zur Datenbank DB-Zugriff über JDBC oder SQLJ l 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, dropjava Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-34 Gespeicherte Prozeduren & Funktionen: Ablauf (Forts.) l 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; – über Deployment-Deskriptor (siehe nächste Folie) l 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 2001/2002 (Dr. C. Türker) 7-35 Lesestoff Registrierung über Deployment-Deskriptoren l 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 2001/2002 (Dr. C. Türker) 7-36 Java-SQL-Datentypen l Verwendung von Java-Klassen als SQL-Datentypen – – Installation von Java-Klassen im DB-Server Unterstützung in Sybase, Informix l Benutzerdefinierter SQL-Datentyp – Klasse mit Attributen und Methoden Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-37 Java-SQL-Datentypen: Implementierung l Klasse mit Schnittstelle java.io.Serializable l Attribute zur Repräsentation von SQL-Daten als public definiert l Zur Ausgabe: Definition der Methode toString l Beispiel: public class AdresseTyp implements java.io.Serializable { public String Strasse; public int Nr; public int PLZ; public String Ort; public String Land; public AdresseTyp() { Strasse = Ort = Land = ""; Nr = PLZ = 0; } ... } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-38 Java-SQL-Datentypen: Installation & Registrierung l Installation von Java-Klassen im DB-Server als JAR-Archiv CALL sqlj.install_jar('file:~/adresse.jar', 'adr_jar', 0); l Registrierung über erweitere Form von CREATE TYPE (Zuordnung der Klasse, Attribute & Methoden) CREATE TYPE AdresseTyp EXTERNAL NAME 'adr_jar:AdresseTyp' LANGUAGE JAVA (PLZ INTEGER EXTERNAL NAME 'PLZ', METHOD AdresseTyp() RETURNS AdresseTyp EXTERNAL NAME 'AdresseTyp', ...); – vordefinierte Prozeduren (wie in Informix) EXECUTE PROCEDURE sqlj.setUDTExtName(SQL-Typname, Java-Klassenname); – Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-39 Java-SQL-Datentypen: Nutzung l Verwendung des Java-Datentyps als Attributtyp CREATE TABLE Kunde ( Name VARCHAR(30), Anschrift AdresseTyp ); l Initialisierung durch Konstruktor INSERT INTO Kunde (Name, Anschrift) VALUES ('Joe', AdresseTyp()); l Zugriff auf Attribute und Methoden mittels SQL-99-Syntax SELECT Anschrift.PLZ, Anschrift.Ort FROM Kunde; Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-40 Lesestoff Anhang JDBC - Beispiele SQLJ - Beispiele JDBC - Beispiel (in Oracle) Lesestoff import java.sql.*; class SelectKunde { public static void main (String args []) throws SQLException { try { // 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:@ordb", "scott", "tiger"); // Erzeuge und führe SQL-Anweisung aus Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT k.Name, k.Anschrift.Ort FROM Kunde k"); // Iteriere durch die Ergebnismenge und gebe Namen und Wohnort aus while (rs.next()) System.out.println(rs.getString(1) + " wohnt in " + rs.getString(2)); rs.close(); // Schliesse die Ergebnismenge stmt.close(); // Schliesse die Anweisung con.close(); // Schliesse die Verbindung } catch (SQLException exc) { System.out.println(exc); // Fehlerbehandlung } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-42 JDBC - Arraybehandlung (in Oracle) Lesestoff import java.sql.*; import oracle.sql.*; // Package für Oracle Object Support public class SelectTelefonArray { public static void main (String args[]) throws Exception { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection con = DriverManager.getConnection("jdbc:oracle:oci8:@ordb", "scott", "tiger"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT Telefone FROM Kunde WHERE Telefone IS NOT NULL"); showResultSet(rs); //Funktion, die alle Elemente der Arrays anzeigt String elements[] = { "0041-1-2332223", "0090-633-23232" }; // Erzeuge neues ARRAY-Objekt ArrayDescriptor desc = ArrayDescriptor.createDescriptor("TELEFONARRAYTYP", con); ARRAY newArray = new ARRAY(desc, con, elements); PreparedStatement ps = con.prepareStatement("UPDATE Kunde SET Telefone = ? WHERE Name = ?"); ((OraclePreparedStatement)ps).setARRAY(1, newArray); ((OraclePreparedStatement)ps).setString(2, "Joe"); ps.execute(); // Führe Update aus rs.close(); ps.close(); stmt.close(); con.close(); } // Methode main ... weiter auf der nächsten Folie Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-43 Lesestoff JDBC - Arraybehandlung (Forts.) public static void showResultSet(ResultSet rs) throws SQLException { int line = 0; while (rs.next()) { line++; // Zugriff auf Array-Informationen ARRAY array = ((OracleResultSet)rs).getARRAY(1); System.out.println ("Array ist vom Typ " + array.getSQLTypeName() + " und hat die Laenge "+ array.length()); // Zugriff auf Array-Elemente String[] values = (String[]) array.getArray(); for (int i=0; i<values.length; i++) { String value = (String) values[i]; System.out.println(">> Telefon " + i + " = " + value); } } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-44 JDBC - Objektbehandlung (in Oracle) Lesestoff import java.sql.*; import oracle.sql.*; public class KundeObject { public static void main (String args []) throws Exception { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection con = DriverManager.getConnection("jdbc:oracle:oci8:@ordb", "scott", "tiger"); Statement stmt = con.createStatement(); Object [] a = new Object [5]; // Erzeuge ein Adresse-Objekt a[0] = "Rheinallee"; a[1] = "69"; a[2] = "8008"; a[3] = "Zurich"; a[4] = "CH"; StructDescriptor addressDesc = StructDescriptor.createDescriptor("ADRESSETYP", con); STRUCT anschriftStruct = new STRUCT(addressDesc, con, adr); PreparedStatement ps = con.prepareStatement("UPDATE Kunde SET Anschrift= ? WHERE Name= ?"); ps.setObject(1, anschriftStruct); ps.setString(2, "Joe"); ps.execute(); // Führe Update aus ResultSet rs = stmt.executeQuery("SELECT Anschrift FROM Kunde WHERE Anschrift IS NOT NULL"); showResultSet(rs); // Zeige alle Anschriften der Tabelle Kunde rs.close(); rs.close(); stmt.close(); con.close(); } // Methode main ... weiter auf der nächsten Folie Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-45 Lesestoff JDBC - Objektbehandlung (Forts.) public static void showResultSet(ResultSet rs) throws SQLException { while (rs.next()) { STRUCT adresse= (STRUCT)rs.getObject(1); Object adresseAttribute [] = adresse.getAttributes(); System.out.println("Strasse: " + adresseAttribute[0]); System.out.println("Nr: " + adresseAttribute[1]); System.out.println("PLZ: " + adresseAttribute[2]); System.out.println("Ort: " + adresseAttribute[3]); System.out.println("Land: " + adresseAttribute[4]); System.out.println(); } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-46 JDBC - Referenzbehandlung (in Oracle) Lesestoff import java.sql.*; import oracle.sql.*; public class TeilRef { public static void main (String args []) throws Exception { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection con = DriverManager.getConnection("jdbc:oracle:oci8:@ordb", "scott", "tiger"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery ("SELECT REF(t) FROM Teil t"); REF ref; STRUCT teil; Object a[]; // Variablendeklarationen while (rs.next()){ // Iteration ueber alle Objektreferenzen ref = (REF) rs.getObject(1); // Zuweisung an Referenzvariable teil = (STRUCT) ref.getValue(); // Zuweisung des Objektwertes a = teil.getAttributes(); // Extraktion der Objektattribute System.out.println("Nr: " + a[0], " Bezeichnung: " + a[1], " Farbe: " + a[2], " Oberteil: " + a[3]); if (((REF) a[3]) != null) { // Ausgabe Nr und Bezeichnung des referenzierten Oberteils a = ((STRUCT) ((REF) a[3]).getValue()).getAttributes(); System.out.println ("Oberteil Nr = " + a[0] + " Bezeichnung = " + a[1]); } } rs.close(); stmt.close(); con.close(); } } 7-47 Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) SQLJ - Beispiel (in Oracle) Lesestoff import java.sql.SQLException; import oracle.sqlj.runtime.Oracle; // Package für SQLJ Support #sql iterator KundeIter(String Name, String Ort); // benannter Iterator class SelectKunde { public static void main (String args []) throws SQLException { try { // Stelle DB-Verbindung her: URL, USER und PASSWD aus Datei connect.properties Oracle.connect(SelectKunde.class, "connect.properties"); // Definition eines Iteratorobjekts KundeIter kunden; // Führe eingebettete SQL-Anweisung aus #sql kunden = { SELECT k.Name AS Name, k.Anschrift.Ort AS Ort FROM Kunde k }; // Iteriere durch die Ergebnismenge und gebe Namen und Wohnort aus while (kunden.next()) System.out.println (kunden.Name() + " wohnt in " + kunden.Ort()); } catch (SQLException exc) { System.out.println(exc); // Fehlerbehandlung } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-48 SQLJ - Arraybehandlung (in Oracle) Lesestoff import java.sql.SQLException; import oracle.sqlj.runtime.Oracle; #sql iterator KundeIter(String Name, TelefonArrayTyp Telefone); // benannter Iterator class SelectTelefonArray { public static void main (String args []) throws SQLException { try { // Stelle DB-Verbindung her: URL, USER und PASSWD aus Datei connect.properties Oracle.connect(SelectTelefonArray.class, "connect.properties"); // Erzeuge neues ARRAY-Objekt und ändere arraywertiges Attribut String telefone [] = { "0041-1-2332223", "0090-633-2323299" }; TelefonArrayTyp array = new TelefonArrayTyp(telefone); #sql { UPDATE Kunde SET Telefone = :array WHERE Name = 'Joe' }; // Definition eines Iteratorobjekts KundeIter iter; // Führe eingebettete SQL-Anweisung aus #sql iter = { SELECT Name, Telefone FROM Kunde WHERE Telefone IS NOT NULL }; // weiter auf der nächten Folie 7-49 Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) SQLJ - Arraybehandlung (Forts.) Lesestoff //Zeige alle Elemente der Arrays an while (iter.next()) { array = iter.Telefone(); // Zugriff auf Array-Informationen System.out.println("Kunde = " + iter.Name()); // Zugriff auf einzelne Array-Elemente String[] values = array.getArray(); for (int i=0; i<values.length; i++) System.out.println((i+1) + ". Telefon = " + values[i]); } // while } catch (SQLException exc) { System.out.println(exc); } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) // Fehlerbehandlung 7-50 SQLJ - Objektbehandlung (in Oracle) Lesestoff import java.sql.SQLException; import oracle.sqlj.runtime.Oracle; #sql iterator AdressIter(AdresseTyp Anschrift); // benannter Iterator class KundeObject { public static void main (String args []) throws SQLException { try { // Stelle DB-Verbindung her: URL, USER und PASSWD aus Datei connect.properties Oracle.connect(KundeObject.class, "connect.properties"); // Erzeuge Anschriftkomponenten String strasse = "Rheinallee"; int nr = 69; int plz = 8008; String ort = "Zurich"; String land = "CH"; // Führe eingebettete SQL-Anweisung aus #sql { UPDATE Kunde SET Anschrift = AdresseTyp(:strasse, :nr, :plz, :ort, :land) WHERE Name = 'Joe' }; // weiter auf der nächsten Folie Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) SQLJ - Objektbehandlung (Forts.) 7-51 Lesestoff // Definition eines Iteratorobjekts AdressIter iter; // Führe eingebettete SQL-Anweisung aus und iteriere über die Ergebnismenge #sql iter = { SELECT Anschrift FROM Kunde WHERE Anschrift IS NOT NULL }; while (iter.next()) { AdresseTyp anschrift = iter.Anschrift(); System.out.println("Strasse: " + anschrift.getStrasse()); // JPublisher generierte System.out.println("Nr: " + anschrift.getNr()); // get-Methoden zum System.out.println("PLZ: " + anschrift.getPlz()); // Zugriff auf System.out.println("Ort: " + anschrift.getOrt()); // Objektattribute System.out.println("Land: " + anschrift.getLand()); } // while } catch (SQLException exc) { System.out.println(exc); // Fehlerbehandlung } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-52 SQLJ - Referenzbehandlung (in Oracle) Lesestoff import java.sql.SQLException; import oracle.sqlj.runtime.Oracle; #sql iterator TeilRefIter(TeilTypRef Teil); // benannter Iterator class SelectTeilRef { public static void main (String args []) throws SQLException { try { // Stelle DB-Verbindung her: URL, USER und PASSWD aus Datei connect.properties Oracle.connect(SelectTeilRef.class, "connect.properties"); // Definition eines Iteratorobjekts TeilRefIter iter; // Führe eingebettete SQL-Anweisung aus und iteriere über die Ergebnismenge #sql iter = { SELECT REF(t) AS Teil FROM Teil t }; // weiter auf der nächsten Folie Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) SQLJ - Referenzbehandlung (in Oracle) 7-53 Lesestoff while (iter.next()) { TeilTypRef ttr = iter.Teil(); TeilTyp t = ttr.getValue(); // JPublisher generierte get-Methode System.out.println("Nr: " + t.getNr() + ", Bezeichnung: "+ t.getBezeichnung()+ " Farbe: " + t.getFarbe() ", Oberteil: " + t.getIstteilvon()); if (t.getIstteilvon() != null) { // Ausgabe Nr und Bezeichnung des Oberteils t = t.getIstteilvon().getValue(); System.out.println ("Oberteil Nr = " + t.getNr() + ", Bezeichnung = " + t.getBezeichnung()); } } // while } catch (SQLException exc) { System.out.println(exc); // Fehlerbehandlung } } } Vorlesung "Objektrelationale, erweiterbare Datenbanken - WS 2001/2002 (Dr. C. Türker) 7-54