Seminar: Java zum Zugriff auf Datenbanken SQLJ

Werbung
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
Herunterladen