Seminar: Java zum Zugriff auf Datenbanken SQLJ Mahboubeh Pakdaman 04.11.2002 Seminar: SQLJ 2 Inhaltsverzeichnis 1. Einleitung 1.1 1.2 1.3 1.4 Was ist SQLJ? SQLJ und wichtige Komponenten Vorteile von SQLJ im Vergleich zu JDBC Vergleich zwischen SQLJ und JDBC 2. SQLJ-Spezifikationen 2.1 Teil 0: Eingebettetes SQL in Java 2.1.1 SQLJ-Anweisungen 2.1.2 SQLJ Host-Ausdrücke/-Variablen 2.1.3 Iteratoren (Einbettung der SELECT-Anweisung) 2.1.4 Verbindungskontext 2.1.5 SQLJ-Interoperatibilität mit JDBC 2.2 Teil 1: Eingebettete Prozeduren bzw. Funktionen in SQLJ 2.2.1 Entwicklung der eingebetteten Prozeduren/Funktionen 2.2.1.1 Implementierung der eingebetteten Prozeduren/Funktionen 2.2.1.2 Installation und Registrierung auf Server 2.2.1.3 Restriktionen 2.3 Teil 2: SQLJ-Datentypen 2.3.1 Implementierung von SQLJ-Datentypen 2.3.2 Installation und Registrierung auf Server 3. Fazit Literaturverzeichnis Seminar: SQLJ 3 1. Einleitung Ohne Datenbankanwendung kommt heutzutage kaum ein Anwendungssystem aus. SQL als eine rudimentäre (non computational complete) Programmiersprache reicht im allgemein nicht aus, um komplette Datenbankanwendungen zu implementieren. HLI (Host Language Interface) und CLI (Call Library Interface) sind zwei Schnittstellen, die in einer prozeduralen Programmiersprache verwendet werden, um Datenbankanwendungen zu erstellen. HLI ist eine Schnittstelle, in der die SQL-Anweisungen in einer prozeduralen Programmiersprache als Host-Sprache eingebettet und die Daten zwischen dem Anwendungsprogramm und der Datenbank durch sogenannte Host-Variablen ausgetauscht werden (wie ESQL (Eiffel SQL library) /C++, ESQL/ADa). Bei dieser Methode wird ein Translator zu Verfügung gestellt, der jede SQL-Anweisungen in die Host-Sprache übersetzt. Die eingebetteten SQL-Anweisungen in einer Host-Sprache kann statisch oder dynamisch sein. Bei statischer Einbettung ist die SQLAnweisungen zur Übersetzungszeit bekannt (wie SQLJ) und bei dynamischer Einbettung werden sie erst zur Laufzeit bekannt gegeben. Es gibt allerdings ein Problem zwischen der SQL- und Host-Sprache. SQL ist eine Sprache, in der eine Menge der Datensätze auf einmal bearbeitet werden können. Im Unterschied dazu können die Host-Sprachen nur einen Datensatz nach den anderen bearbeiten. Um diesen Unterschied zu überbrücken wird ein Datenpuffer benutzt, in dem jedesmal die Ergebnismenge der SQL-Anfrage gespeichert werden. Ein Zeiger zeigt auf den bearbeitenden Datensatz, der Cursor genannt wird. CLI ist die andere Schnittstelle, in der ein oder mehrere Bibliotheken charakterisiert werden und deren Funktionen mit Hilfe einer prozeduralen Programmiersprache von einem Anwendungsprogramm aufgerufen werden (wie JDBC). 1.1 Was ist SQLJ? SQLJ ist eine standardisierte Sprache mit statisch eingebettetem SQL in Java. Die Grundlagen von der Sprache wurden von einem Konsortium aus mehreren Datenbankherstellern (Oracle, Compaq/Tandom, Javasoft, IBM, Informix und Sybase) festgelegt, die dann von ANSI (Amercian National Standard Institute) übernommen wurden (ANSI-Standard X3.135,,Information tecnology -Database languages – SQL – Part 10:SQL/OLB,,). Das Ergebnis ist eine Spezifikation, die in drei Teile unterteilt ist: Teil 0, Teil 1 und Teil2 (Dies wird später ausführlich behandelt). 1.2 SQLJ und wichtige Komponenten Man kann die Phasen, die ein SQLJ-Programm (.sqlj Datei) von der SQLJ-Quelle bis zu seiner Ausführung durchläuft graphisch darstellen, siehe Abbildung 1.2. Seminar: SQLJ 4 Abbildung 1.2 Für diesen Durchlauf enthält SQLJ vier wichtige Komponenten: ? ? ? ? Translator SQLJ-Profile Customizer SQLJ-Laufzeitbibliothek Das SQLJ-Quellprogramm kann von dem Java-Compiler nicht ohne weiteres direkt verarbeitet werden. Ein wichtiges Ergebnis der Zusammenarbeit der Datenbankhersteller ist die Implementierung eines gemeinsamen Translators für alle Datenbanksysteme. Der SQLJ-Translator ist in Java geschrieben. Seine Aufgabe ist, die SQLJ-Quelle in Java-Code zu übersetzen und ein oder mehrere SQLJ-Profiles zu erzeugen. SQLJProfile enthält Informationen über SQL -Anweisungen, sowie überTyp und Übergaberichtung der Parameter und Ergebnisdaten. SQL-Profile ist Instanz der Klasse sqlj.runtime.profile.Profile. Durch Customizer werden die SQLJ-Profiles an Herstellerspezifikationen angepasst. Aus diesem Grund enthält das SQLJ-Profile die ausführbaren SQL-Anweisungen, die während der Übersetzung durch JDBC-Aufrufe ersetzt werden können. Customizer ist eine Komponente, die automatisch von SQLJ aufgerufen wird. Seminar: SQLJ 5 Die SQLJ-Laufzeitbibliothek ist genauso wie der Translator in Java geschrieben. Sie ist definiert als Menge von Java -Klassen der folgenden Packages: sqlj.runtime, sqlj.runtime.ref, sqlj.runtime.profile, sqlj.runtime.profile.ref und sqlj.runtime.error. Ihre Aufgabe ist, die Operationen in SQL -Anweisungen zu implementieren und auf die Datenbank zuzugreifen. Nach der Übersetzung durch den Translator, in dem ein SQLJ-Quellcode in JavaCode übersetzt und SQL -Anweisungen durch JDBC-Aufrufe ersetzt worden sind, wandelt die SQLJ-Laufzeitbibliothek den Java-Bytecode in ein JDBC-Programm um. Danach werden mit Hilfe eines JDBC-Treibers die JDBC-Aufrufe auf die Datenbank realisiert. 1.3 Vorteile von SQLJ im Vergleich zu JDBC SQLJ vereinfacht die Erstellung, Verwaltung und das Debugging der Java Applikationen mit den Datenbankzugriffen. SQLJ basiert auf dem Einbettungsprinzip d. h. statische SQL -Anweisungen können bereits zur Übersetzungszeit überprüft und fehlerhafte Anweisungen oder Typkonflikte erkannt werden. Es vereinfacht die Entwicklungskosten, weil eine leichtere Methode benutzt wird, um SQL direkt in Java einzubetten. SQLJ ist kompakt und besser lesbar. 1.4 Vergleich zwischen SQLJ und JDBC Wir betrachten den folgenden JDBC Code, der nach dem Namen eines Mitarbeiters fragt. Die Kriterien sind „Gehalt“ und „Personalnummer“ des Mitarbeiters:[2] //JDBC String name; int id=37115; float salary=2000; PreparedStatement pstm=con.preparedStatement( “SELECT ename FROM emp WHERE empno=? And sal >? ”) ; pstmt.setInt(1,id); pstmt.setFloat(2,salary); ResultSet rs=psmt.executeQery(); while(rs.next()) { name=rs.getString(1); System.out.println(“Name is :”+name); } rs.close(); psmt.close(); //SQLJ //Das folgende Beispiel in SQLJ-Code zeigt den Unterschied zu //JDBC für das vorherige Beispiel: String name; int id=37115; float salary=2000; #sql {SELECT ename INTO :name FROM emp WHERE empno=:id AND Seminar: SQLJ 6 sal> :salary}; System.out.println(“Name is :”+name); Im Vergleich zum JDBC-Code ist SQLJ für die gleiche SQL-Query übersichtlicher und einfacher zu schreiben. 2. SQLJ-Spezifikationen SQLJ bietet eine aus mehreren Teilen bestehende Spezifikation für die Benutzung von SQL in Java an. Diese Spezifikation wird in drei Teile unterteilt: Teil 0 beschreibt die Syntax für statische SQL. Teil 1 beschreibt, wie die benutzerdefinierte JavaProzeduren bzw. Funktionen implementiert und Teil 2 beschreibt, wie die benutzerdefinierte SQL-Datentypen implementiert werden können.[4] 2.1 Teil 0: Eingebettetes SQL in Java Teil 0 unterstützt statische SQL-Anweisungen und basiert auf dem Einbettungsprinzip, womit die SQL-Anweisungen direkt in den Java-Quelltext eingefügt werden. Aus diesem Grund ist eine bestimmte Syntax erforderlich. Part 0 beschreibt diese S yntax und folgende Komponenten: ? SQLJ Host-Ausdrücke/-Variablen ? Iteratoren ? Verbindungskontext Zuerst betrachten wir die Anweisungen in SQLJ. 2.1.1 SQLJ-Anweisungen SQLJ besteht aus einer Menge von Anweisungen. SQLJ-Anweisungen werden hinter dem Präfi x #sql geschrieben und können in zwei Gruppen unterteilt werden: 1. SQLJ-Klausel 2. Anweisungen für Deklaration der Iteratoren und Verbindungskontexte (Dies folgt später) SQLJ-Klauseln sind ausführbare SQL-Anweisungen. Sie werden in geschweifte Klammern geschrieben und durch ein Semikolon abgeschlossen. #sql { sql-Operationen}; Eine solche Klausel kann überall dort eingefügt werden, wo in Java eine Anweisung stehen kann. Alles was zwischen den geschweiften Klammern steht, muss der SQLSyntax entsprechen. Eine Klausel kann ? ? eine Zuweisungsklausel oder eine Anweisungsklausel Seminar: SQLJ 7 sein. Eine Zuweisungsklausel enthält einen oder mehrere Ausgabewerte, wie z. B. beim Aufruf einer gespeicherten Funktion oder bei Anfragen, wobei die Abfrage einen einzigen Datensatz liefern muss. #sql { SELECT name, umsatz INTO :name,:umsatz From kunden = :kundernnr } Eine Anweisungsklausel liefert keine Ausgabewerte. Jede DDL-Anweisungen (Data Definition Language) und DML-Anweisungen (Data Manipulation Language), außer SELECT, sind Beispiele dafür. #sql{INSERT mitarbeiter VALUES (:nr, :name, :vorname, :abtnr)} 2.1.2 SQLJ Host-Ausdrücke/-Variablen Die SQLJ-Ausdrücke sind die gewöhnlichen Java-Ausdrücke, die sich in eingebetteten SQL-Anweisungen befinden. Sie tauschen die Daten zwischen dem SQLJ-Programm und der Datenbank aus. Host-Variablen ist die einfachste Form eines Host-Ausdrucks. Sie können Datentypen haben, die in Java erlaubt sind. Bei Verwendung der Host-Varíablen muss aber auf korrekte Typkonvertierung zwischen den SQL-Datentypen und entsprechenden Java-Datentypen geachtet werden (Tabelle 2.1.2). Man kann auch optional die Richtung des Datenflusses mit den Host-Ausdrücken angeben. Es können IN-, OUT- oder INOUT-Richtungen angegeben werden. Standardmäßig werden die OUT für SELECT INTO-Anweisung, sowie FETCHAnweisung und IN für alle anderen Ausdrücken angenommen. Für einfache HostVariablen wird die Richtungsangabe durch ein Leerzeichnen vom Variablenamen getrennt, Ausdrücke sind dagegen in Klammern zu setzen. IN bezeichnet, dass der Wert des Host-Ausdrucks von der SQL-Anweisung gelesen wird. Z. B.: float balace=1345.0; float minRatio=0.05; #sql { UPDATE creditAcc SET minPayment= :IN(balance*minRatio) WHERE accnum=484848}; OUT bedeutet, dass der Wert des Host-Ausdrucks durch die SQL-Anweisung geändert wird. IN und OUT müssen nicht immer explizit angegeben werden, weil sie vom SQLJ-System impliziert werden. Z. B.: String emname; #sql { SELECT ename :OUT empname FROM emp WHERE enum=37373}; INOUT bedeutet, dass der Wert des Host-Ausdrucks durch die SQL -Anweisung sowohl gelesen als auch geändert wird. INOUT muss aber vor einem Host-Ausdruck explizit angegeben werden. Seminar: SQLJ 8 SQL type ________________________________________ CHAR VARCHAR LONGVARCHAR NUMERIC DECIMAL BIT TINYINT SMALLINT INTEGER BIGINT REAL FLOAT DOUBLE BINARY VARBINARY LONGVARBINARY DATE TIME TIMESTAMP Java Type _________________________________________ String String String java.math.BigDecimal java.math.BigDecimal Boolean Byte Short Int Long Float Double Double byte[] byte[] byte[] java.sql.Date java.sql.Time java.sql.Timestamp Tabelle 2.1.2 2.1.3 Iteratoren (Einbettung der SELECT-Anweisung) Bei der SELECT-Anweisung können ein oder mehrere Datensätze als Ergebnis zurückgeliefert werden. Falls eine Abfrage einen Datensatz zurückliefert, kann es direkt von Java abgearbeitet werden, da Java zu einem Zeitpunkt einen einzelnen Datensatz abarbeiten kann. Die SELECT-Anweisung mit mehreren Datensätzen als Ergebnismenge können aber nicht direkt von Java abgearbeitet werden. Iteratoren entsprechen den Cursorn in Java, in dem die Ergebnismenge der SELECT-Anfrage abgespeichert und satzweise dem Java -Programm übergeben werden. Der wichtigste Unterschied zwischen einem Cursor und einem Iterator ist, dass Iteratoren Instanzen der Iterator-Klasse sind. Sie gehören zur Java-Sprache und können außer als SQL -Anweisungen deklariert, als Parameter einer Methode übergeben werden. Cursor gehören aber nicht zu Java. Sie sind SQL -Objekte der SQL-Spezifikation. Iteratoren sind auch mit den ResultSets von JDBC vergleichbar. Während in einem ResulltSet der Spaltenwert beliebige SQL-Datentypen annehmen kann, sind die SQLJ-Iteratoren streng typisiert. In SQLJ gibt es zwei Arten von Iteratoren: 1- In den benannten Iteratoren müssen die Namen der Attributen mit den Namen der entsprechenden Spalten in der SELECT-Anweisung übereinstimmen (die Reihenfolge ist nicht relevant). Um einen benannten Iterator in einem SQLJProgramm zu verwenden, sind folgende Schritte notwendig: Seminar: SQLJ ? ? ? ? ? ? 9 Deklaration einer Iterator-Klasse, in der eine Liste von Attributen aus Typ und Bezeichnungen angegeben werden. Der SQLJ-Translator ersetzt die Iterator-Deklaration bei der Übersetzung durch eine Java-Klasse mit dem gleichen Namen. Deklaration einer Iterator Instanz. Erstellung der Methoden, die Werte der entsprechenden Spalten zurückgeben Zugriff auf den aktuellen Datensatz der Ergebnismenge mit Hilfe der next()Methode. Lesen der Spaltenwerte des aktuellen Datensatzes. Schließen der Iterator-Instanz mit Hilfe der close()-Methode. #sql public iterator Byname( String isbn ,String title); Byname iter; #sql iter={ SELECT isbn , title FROM book }; while( iter.next()){ System.out.println(“title=”+iter.title()); System.out.println(“title=”+iter.isbn()); iter.close(); 2- Mit positionierten Iteratoren wird die Übereinstimmung zwischen den Attributen in der Iterator-Deklaration und den entsprechenden Spalten in der SELECT-Anweisung über ihre Positionen ermittelt. Bei der Deklaration wird nur eine Liste von Typen angegeben, wobei die Reihenfolge der Datentypen relevant ist. Mit Hilfe der FETCH-Anweisung erfolgt der Zugriff auf den aktuellen Datensatz der Ergebnismengen. Die endFetch()-Methode liefert true, wenn das Ende der Ergebnismenge erreicht worden ist. #sql iterator ByPos( String, Flaot); ByPos iter ; String title; float price; #sql iter={ SELECT title, price FROM book}; while(true) { #sql{ FETCH : iter INTO :title , : price}; if(iter.endFetch()) break; System.out.println(“title=”+title); System.out.println(“price=”+price); } iter.close(); 2.1.4 Verbindungskontext Eine Verbindung zur Datenbank wird in SQLJ grundsätzlich durch einen Verbindungskontext realisiert. #sql context ctx-name; Mit dieser Deklaration wird eine Klasse mit gleichem Namen durch den Translator von sql.runtime.ConnectinContext abgeleitet. Es gibt eine Reihe von Konstruktoren in Seminar: SQLJ 10 der Klasse, worüber eine Verbindung zur Datenbank hergestellt und SQLOperationen ausgeführt werden kann. Z. B.: Mycontext ctx=null; try { ctx= new MyContext (url,false); #sql [ctx] { sql-Operation }; ctx.close(); } Mit der close-Methode wird die Verbindung geschlossen. Eine andere Möglichkeit bietet die Klasse sqlj.runtime.ref.DefaultContext. Nach dem Erzeugen einer Instanz dieser Klasse über eine geöffnete JDBC-Verbindung kann dieser Kontext als DefaultContext festgelegt werden. Im weiteren Verlauf des Programms wird das Kontext-Objekt über die Methode getDefaultContext() ermittelt. Mit der close-Methode wird dann die Verbindung geschlossen. Connection con = DriverManager.getConnection (url,”user”, “password”) ; DefaultContext ctx =new DefaultContext (con); DefaultContext.setDefaultContext (ctx); …........ …......... DefaultContext ctx =DefaultContext.getDefaultContext(); Connnection con=ctx.getConntection(); SQLJ unterstützt die gleichzeitige Verbindung mit unterschiedlichen Schemata oder Datenbanken. Dafür wird entweder zu jeder Verbindung ein DefaultContext -Objekt wie oben erzeugt und die Verbindung mit Hilfe der setDefaultContext-Method vor der entsprechenden SQL -Operation eingesetzt oder die Verbindung-Instanz wird in eckigen Klammern vor der zugehörigen SQL-Operation eingesetzt. Z. B: Entweder: DefaultContext.setDefaultContext(ctx1); #sql { SQL-Opration} ........... ........... DefaultContext.setDefaultContext(ctx2); #sql { SQL-Opration} ........... Oder: #sql [ctx1] { SQL-Operation}; #sql [ctx2] { SQL-Operation}; 2.1.5 SQLJ-Interoperabilität mit JDBC Das SQLJ bietet die Möglichkeit, sowohl statisches als auch dynamisches SQL in einer SQLJ-Datenbankanwendung auszuführen. Bei Interkompatibilität handelt es sich um zwei Punkte: 1. Die Konvertierung zwischen Verbindungskontext und JDBC-Verbindung. Seminar: SQLJ 11 Die JDBC-Verbindung ist nötig, wenn eine dynamische SQL -Operation durchgeführt werden muss. DefaultContext und deklarierte Kontext -Klassen können über die getConnection-Methode als JDBC-Verbindung eingesetzt werden. Es handelt sich um eine gemeinsame Verbindung. Das heißt, wird die JDBC-Verbindung mit close()-Methode geschlossen, so wird damit auch die Kontextverbindung geschlossen. Z. B: Void doDynamicQuery (String condition) Connection con; con=DefaultContext.getDefaultContext().getConnection; StringBuffer query=new StringBuffer(“SELECT isbn FROM book”); Statement stmt=con.createStatement(); ResultSet rset; rset.executeQuery (query.ToString()); While (rset.next()){...} rset.close(); Wenn auch eine aktive JDBC-Verbindung als Kontext in einer SQLJ-Klausel eingesetzt werden muss, gibt es die Konvertierungsmöglichkeit, wobei die JDBCVerbindung als Parameter des Kontext-Konstruktors übergeben wird. Z. B.: #sql context Mycontext; mycontext ctx=new Mycontext(con); #sql [ctx { SQL-Operation }; 2. Die Konvertierung zwischen Iteratoren und ResultSet. Während Iteratoren streng typisiert sind, ermöglicht das JDBC-ResultSet einen Zugriff auf die Anfrageergebnisse. SQLJ bietet die Möglichkeit einen Iterator (benannte oder positioniert) in ein ResultSet umzuwandeln. Der Iterator muss als public deklariert sein. Am Ende kann der Iterator mit der close geschlossen werden, nicht das ResultSet. Z. B.: #sql public iterator Cursor1 (String, String, String); Cursor1 curs; ..... ResultSet rs=curs.getResultSet(); While(rs.next()) { ....... } Curs.close(); Und um eine Instanz der Klasse ResultSet in einem Iterator (benant oder positioniert) zu konvertieren, wird die CAST-Methode mit deklarierten ResultSet als Host-Variable verwendet. Z. B.: #sql public iterator ByName(String title, double preice); ResultSet rs; ByName curs; #sql curs=(CAST :rs); while(curs.next()) {.........} curs.close(); Seminar: SQLJ 12 2.2 Teil 1: SQLJ gespeicherte Prozeduren/Funktionen Bei Teil 1 handelt es sich um Prozeduren und Funktionen in Java, die im Datenbankserver gespeichert sind. Diese Prozeduren/Funktionen können auch dort ausgeführt werden und lokal auf Datenbank zugriffen. Dafür muss das DBMS JavaVM (Virtual Machine) haben, um die Methoden auszuführen und auf Daten lokal zugreifen zu können (Abbildung 2.2). Applikation CALL proc Applikation CALL proc ____________________________________________________________ Java-VM Java-Prozeduren Methoden Abbildung 2.2 Die Speicherung und Ausführung von Prozeduren und Funktionen im Datenbankserver hat gegenüber der reinen clientseitigen Implementierung Vorteile, die sich vor allem aus dem lokalen Zugriff und der zentralen Verwaltung ergeben: - Da die Daten nicht bei jedem Zugriff vom Server zum Client bewegt werden müssen, kann die Netzwerkbelastung reduziert werden. - Bei den Anwendungen mit einer Vielzahl von Datenbankzugriffe, kann die Performance gesteigert werden. - Die zentrale Speicherung und Verwaltung der Prozeduren in der Datenbank ermöglicht die Anwendung von Datenbankdiensten wie Auswertung, Backup, Recovery und Replikation. - Der Administrationsaufwand wird gesenkt, da die Datenverteilung gesenkt wird. - Da die eingebettete Prozeduren im Datenbankserver ausgeführt werden, sind sie unabhängig von der Client-Umgebung, um damit die Portabilität gesteigert zu werden. 2.2.1 Entwicklung der eingebetteten Prozeduren/Funktionen Seminar: SQLJ 13 Obwohl die Verwendung der Java bei der Erstellung von gespeicherten Prozeduren/Funktionen eine Vereinheitlichung sein soll, existieren große Unterschiede bei den verschiedenen Date nbanksystemen um ein Datenbankobjekt zu registrieren. Die Entwicklung eines SQLJ-Programms , das eine gespeicherte Prozedur bzw. Funktion erstellt, wird bei Oracle in folgenden Schritten durchgeführt. 1. Implementieren und übersetzen des SQLJ-Programms 2. Installation und Registrierung auf Server 3. Aufrufen der gespeicherte n Prozeduren/Funktionen 2.2.1.1 Implementierung der eingebetteten Prozeduren/Funktionen Bei der Klasse Routine handelt es sich um eine Klasse, die preise()-Methode (static) definiert. Diese Klasse wird auf dem Datenbankserver gespeichert und ihre Methode kann dann vom Client oder (Server) aufgerufen werden. import java.sql /* Iterator-Kelassen deklarieren */ #sql iterator Iter (double sum) ; public class Routine { /* Methoden definieren public static void preise(int orderNr) { Iter iter; Double res=0.0; #sql iter={SELECT sum(b.preise * oi.num) FROM order oi, book b WHERE oi.orderID= :orderNr AND oi.isbn=b.isbn}; if(iter.next()) res=iter.sum(); return res } 2.2.1.2 Installation und Registrierung auf Server Nach dem obigen Beispiel wird Routine.java durch einen Translator aus Routine.sqlj erzeugt und damit werden die SQL-Anweisungen kompiliert. Der kompilierte Java-Code wird in einem JAR-Archiv zusammengepackt. Hierfür kann z. B. das Java-Werkzeug jar verwendet werden. > > javac Routine.java jar cvfM Routinet.jar Routine.class Seminar: SQLJ 14 Das jar-Archiv muss dann dem Datenbanksystem bekannt gemacht werden, d. h. vorher erstellte Archiv routine.jar kann mit folgender SQL-Anweisung auf dem Server installiert bzw. registriert werden: CREATE FUNKTION preise ( orderNr INTEGER) RETURNS DOUBLE EXTERNAL NAME 'routine_jar:Routine.preise' LANGUAGE JAVA PARAMETER STYLE JAVA; Gespeicherte Prozeduren werden in SQLJ durch das vorangestellte Schlüsselwort CALL aufgerufen: #sql result = { CALL (func (preise)) } Im Gegensatz dazu erfolgt der Aufruf von eingebetteten Funktionen, die einen Wert zurückgeben, über das Schlüsselwort VALUES. #sql result ={ VALUES ( func (parameterliste) ) }; 2.2.1.4 Restriktionen Die Implementierung von gespeicherten Prozeduren hat manche Restriktionen. Diese Restriktionen sind: - Es ist keine direkte Interaktion mit dem Nutzer möglich, d. h. es können keine GUI-Funktionen realisiert werden. Ebenso ist kein Zugriff auf das lokale Dateisystem erlaubt. - Es besteht eine Default -Verbindung zur lokalen Datenbank, weitere Verbindungen können nicht aufgebaut werden. - Prozeduren und Funktionen sind als Klassenmethoden zu implementieren (statische Methode). Dies trifft jedoch nicht für IBM DM2 zu. Hier sind gespeicherte Objekte, die von der Klasse StoredProc abgeleitet sind und vor dem Aufruf instantiiert werden. 2.3 Teil 2: SQLJ Datentypen Teil 2 handelt sich um die Nutzung von Java-Klassen zur Implementierung von SQLDatentypen. Es geht um die Installation der Klassen im Datenbankserver und deren Nutzung als echte SQL-Datentypen. Diese Datentypen werden durch die gleichen Schritte wie bei der Entwicklung der Funktionen entwickelt. 1. Implementieren der SQLJ-Datentypen 2. Installation und Registrierung auf einem Server 2.3.1 Implementierung der SQLJ-Datentypen Die Implementierung von SQL-Typen bzw. SQL-Klassen basiert im wesentlichen auf Implementierung der java.io.Serializable- oder java.sql.SQLData Schnittstelle in Java. Weiterhin müssen alle Attribute in der implementierten SQL-Klasse als public Seminar: SQLJ 15 definiert werden. Zur Ausgabe der Daten ist es außerdem notwendig, die Methode toString zu implementieren. Z. B.: . public class Address implements java.io.Serializable { public int zipcode; public String city; public String street; public Address() { zipcode=0; city =street = “”; public Address zipcode=zip; city=c; street=s; ( } int zip , String } public String toString () c , String s) { { return zipcode + “ ” + city + “ , ” + street; 2.3.2 Installation und Registrierung auf Server Wie gespeicherte Prozeduren müssen SQL-Datentypen vor ihrer Verwendung im Datenbanksystem installiert werden. Wie dieses konkret erfolgt, ist vom DBMS abhängig. Die wichtigste ist installer_jar, die eine JAR-Datei durch eine URL und das aktuelle Schema unter dem gegebenen Namen installiert. CALL sqlj.installer_jar ( ’ file:/adresse.jar ’ , ’addr_jar’); Für die Registrierung wird die SQL-Anweisung CREATE TYPE verwendet. Eine mögliche SQL-Typdefinition für das obige Beispiel könnte daher wie folgt lauten: CREATE TYPE Addr EXTERNAL NAME ’ addr_jar :Address’ LNGUAGE JAVA ( zip INTEGER EXTERNAL NAME ‘ zipcode ’ , city VARCHER (30) EXTERNAL NAME ’ city ’ , street VARCHER ( 30 ) EXTERNAL NAME ’ street ’ , METHOD Addr () RETURN Addr EXTERNAL NAME ‘ Address ’ , METHOD Addr ( zip INTEGER , c VARCHER (30) , s VARCHER (30) ) Addr EXTERNAL NAME ‘ Address’ , METHOD to-string () RETURN VARCHER (225) EXTERNAL ‘NAME‘toString ’); Seminar: SQLJ 16 3. Fazit/Zusammenfassung SQLJ und JDBC arbeiten zusammen, um ein komplettes Set von Optionen für statisches und dynamisches SQL anzubieten. Die SQLJ-Spezifikationen präsentieren ein Modell, womit die statischen SQLOperationen direkt in Java angewendet werden können. Es macht die Entwicklung der Java -Applikationen mit Datenbankzugriff einfacher, schneller und portabel. Daher wird Java für viele Business-Applikationen akzeptabler. Literaturverzeichnis [1] : http://www.sqlj.org/implement/oracle/sqlj/README.txt [2]: http://www.oracle.com/oramag/oracle/99-May/39idev2.html?view=print [3]: http://bach.towson.edu/docs/software/sqlj-0.7.1.1 BETA/sqlj_spec.htm#TUTORIAL [4]: http://www.devx.com/dbzone/articles/sqlj/ [5 ]: http://www.odbmsfacts.com/articles/sqlj.html [6]: http://www.javaworld.com/javaworld/jw-05-1999/jw-05-sqlj-p2.html [7]: Datenbanken & Java : Gunter Saake-Kai-Uwe Sattler [8]: Java in Datenbanksystemen: Petkovic und Brüderl