Verlagerung von Java-Anwendungen in die Datenbank (Teil I)

Werbung
Verlagerung von Java-Anwendungen
in die Datenbank (Teil I)
Autor: Markus Fiegler, ORDIX AG
DOAG News Q2_2005
Dieses Werk ist urheberrechtlich geschützt. Die dadurch begründeten Rechte, insbesondere die der
Übersetzung, des Nachdrucks, des Vortrags, der Entnahme von Abbildungen und Tabellen, der Funksendung, der Mikroverfilmung oder der Vervielfältigung auf anderen Wegen und der Speicherung in
Datenverarbeitungsanlagen, bleiben, bei auch nur auszugsweiser Verwertung, vorbehalten. Eine
Vervielfältigung dieses Werkes oder von Teilen dieses Werkes ist auch im Einzelfall nur in den
Grenzen der gesetzlichen Bestimmungen des Urheberrechtes der Bundesrepublik Deutschland vom
9. September 1965 in der jeweils geltenden Fassung zulässig. Sie ist grundsätzlich vergütungspflichtig. Zuwiderhandlungen unterliegen den Strafbestimmungen des Urheberrechtsgesetzes.
©2005
Oracle stellt seit der Datenbank-Version 8.1.5 eine Java Virtual Machine (JVM) zur Verfügung.
Damit lassen sich Java-Anwendungen innerhalb der Datenbank ausführen. Beispiele zeigen, wie
Java-Anwendungen in eine Oracle-10g-Datenbank geladen und ausgeführt werden. Gleichzeitig wird
ein Sicherheitskonzept in Bezug auf die Java-Klassen und die Anwendungsmöglichkeiten von Java
Stored Procedures erläutert.
Einsatz von Java Stored Procedures
In den meisten Fällen wird die Geschäftslogik sowohl von einer Datenbank-Anwendung als auch von
Batch-Programmen aufgerufen. Mithilfe der Stored Procedures kann die Funktionalität zentral in der
Datenbank abgelegt und von einer Dialog-Anwendung oder einem Batch-Programm verwendet
werden. Durch die Nutzung von Stored Procedures lässt sich somit die Wiederverwendbarkeit der
einzelnen Anwendungskomponenten steigern und die Komplexität der Anwendungen deutlich reduzieren. Da die Stored Procedures bereits kompiliert in der Datenbank aufbewahrt werden, ist außerdem eine schnelle Ausführung und ein direkter Datenzugriff möglich, was eine gute Performance
sicher stellt.
Ein großer Nachteil von Stored Procedures ist jedoch die Datenbank-Abhängigkeit, denn die meisten
Datenbank-Hersteller stellen dafür eine eigene Datenbank-Programmiersprache zur Verfügung.
Stored Procedures lassen sich deshalb nur mit hohem Aufwand von einem Datenbank-System auf ein
anderes migrieren. Um dieses Problem zu lösen, greift man auf die so genannten Java Stored
Procedures zurück. Sie werden in Java erstellt und können auf jedem Rechner-System mithilfe einer
Java Virtual Machine interpretiert und ausgeführt werden. Der Datenbank-Zugriff einer Java Stored
Procedure wird mit einem JDBC-Datenbank-Treiber sicher gestellt, der für alle herkömmlichen
Datenbank-Systeme verfügbar ist.
OracleJVM
OracleJVM ist eine in den Kernel von Oracle implementierte Java Virtual Machine (JVM). Ab der
Version 10g stehen J2SE 1.4 (Java 2 Standard Edition) und der Datenbank-Treiber JDBC 3.0 zur
Verfügung. Somit können Java-Programme, die in einer OracleJVM Version 10g ablaufen, den vollen
Umfang der Java-Funktionsbibliotheken von J2SE 1.4 nutzen. Die Java-Funktionsbibliotheken von
J2SE liegen in einem $ORACLE_HOME/javavm/admin-Verzeichnis auf dem Datenbank-Rechner.
Da der vom Java-Compiler erstellte Java-Bytecode zur Laufzeit vom Interpreter (OracleJVM)
interpretiert und ausgeführt wird, entstehen Ineffizienzen bei der Programmausführung.
Um diesen Engpass zu beseitigen, sind alle Java-Funktionsbibliotheken mit einem Betriebssystemabhängigen Native-Compiler übersetzt. Ein Native-Compiler übersetzt den Java-Bytecode einer JavaKlasse in einen Betriebssystem-abhängigen Programm-Code und senkt damit deutlich die
Ausführungsgeschwindigkeit von Java-Programmen, die innerhalb von OracleJVM ablaufen. Oracle
bietet auch die Möglichkeit, selbst entwickelte Java-Klassen mit einem Native-Compiler zu übersetzen.
©2005
Java-Anwendungen für die OracleJVM
Bei der Entwicklung sind folgende Besonderheiten zu beachten:
- Jede statische Methode kann als Programm-Einstiegspunkt verwendet werden.
- Es gibt keine Unterstützung für GUI-Komponenten wie AWT und Swing.
- Multi-Threading wird nicht unterstützt.
- Es muss der Server-seitige JDBC-Treiber verwendet werden.
Der Programm-Einstiegspunkt
In einer herkömmlichen JVM-Umgebung stellt die main-Methode einer Java-Klasse den Einstiegspunkt eines Programms. Beim Starten einer Klasse mit dem Kommando java wird die main-Methode
dieser Klasse aufgerufen. Der Einstiegspunkt einer in der Datenbank gespeicherten Java-Klasse
kann eine beliebige statische Methode dieser Klasse sein.
Keine Unterstützung für GUI-Komponenten wie AWT und Swing
Da es sich bei den Java-Anwendungen, die innerhalb einer OracleJVM ablaufen, um Server-seitige
Anwendungen handelt, ist die Verwendung von grafischen Komponenten (GUIs) nicht sinnvoll. Daher
wird die Erzeugung von Instanzen der GUI-Objekte wie z. B. AWT und Swing nicht unterstützt.
Allerdings kann die GUI-Funktionalität wie z.B. die Erstellung und Manipulation von Bildern verwendet
werden, solange die erstellten beziehungsweise veränderten Bilder nicht angezeigt werden.
Fehlende Unterstützung für Multi-Threading-Verfahren
Eine weitere Besonderheit bei der Entwicklung von Java-Anwendungen für die OracleJVM ist die
fehlende Unterstützung für das Multi-Threading-Verfahren. In einer OracleJVM werden alle Threads
nacheinander statt gleichzeitig ausgeführt. Java-Anwendungen müssen allerdings wegen dieser
Besonderheit nicht extra angepasst werden; sie können unverändert in der Server-seitigen OracleJVM
ausgeführt werden.
Server-seitige JDBC-Treiber
Beim Zugriff von Java Stored Procedures auf die Datenbank-Inhalte muss ein Server-seitiger JDBCTreiber benutzt werden. Bei der Verwendung dieses Datenbank-internen JDBC-Treibers sind folgende
Punkte zu berücksichtigen:
- Der Server-seitige JDBC-Treiber muss im Programm nicht registriert werden, da dieser bereits
im Oracle-Server integriert ist.
- Die Datenbank-Verbindung kann nicht physisch geschlossen werden.
- Die Verwendung von Auto-Commits wird nicht unterstützt.
- Eine Verbindung zu einer entfernten Datenbank ist mit dem Server-seitigen JDBC-Treiber
nicht möglich.
- Die JDBC-Datenbank-Verbindung wird mit der Zeichenkette „jdbc:default:connection:“
ermittelt, z.B. DriverManager.getConnection („jdbc:default:connection:“).
©2005
Java-Klassen ohne Datenbank-Zugriff
Die oben beschriebenen Besonderheiten bei der Entwicklung von Java-Anwendungen für die
OracleJVM beziehen sich auf Java-Klassen, die einen Datenbank-Zugriff enthalten. Java-Klassen, die
über keinen Datenbank-Zugriff verfügen, muss man nicht anpassen. Sie können ohne Änderungen in
der OracleJVM-Umgebung verwendet werden.
Erstellung von Java-Klassen
Java-Klassen, die aus einer Java Stored Procedure aufgerufen werden, können mit Hilfe einer
beliebigen Java-Entwicklungsumgebung, wie z.B. JDeveloper erstellt, kompiliert und getestet werden.
Der nachfolgende Quellcode stellt eine typische Client/Server-Java-Datenbank-Anwendung dar, die
auf einem Client mit einer Java-Virtual-Machine lokal aufgerufen wird.
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.driver.*;
public class Mitarbeiter extends Object {
public static void setGehalt(int ma_nr, int gehalt) {
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl10","mf","mf");
String sqlUpdate = "UPDATE ma SET gehalt = ? WHERE ma_nr = ?";
PreparedStatement pstmt = conn.prepareStatement(sqlUpdate);
pstmt.setInt(1, gehalt);
pstmt.setInt(2, ma_nr);
pstmt.executeUpdate();
conn.close();
pstmt.close();
} catch(Exception e) { e.printStackTrace(); }
}
public static void main(String[] args) { setGehalt(1, 900); }
}
Um das Programm in eine Oracle-Datenbank zu verlagern, müssen die zuvor dargestellten
Besonderheiten bei der Entwicklung von Java-Anwendungen für die OracleJVM berücksichtigt
werden. Der nachfolgende Quellcode zeigt die bereits für die Ausführung in der Datenbank veränderte
Klasse Mitarbeiter.
©2005
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.driver.*;
public class Mitarbeiter extends Object {
public static void setGehalt(int ma_nr, int gehalt) {
try {
//DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection(
"jdbc:default:connection:");
String sqlUpdate = "UPDATE ma SET gehalt = ? WHERE ma_nr = ?";
PreparedStatement pstmt = conn.prepareStatement(sqlUpdate);
pstmt.setInt(1, gehalt);
pstmt.setInt(2, ma_nr);
pstmt.executeUpdate();
//conn.close();
pstmt.close();
} catch(Exception e) { e.printStackTrace(); }
}
}
In der Klasse Mitarbeiter, die für die Ausführung im OracleJVM angepasst wurde, sind zum einen die
Registrierung des JDBC-Treibers entfernt und die Ermittlung der Server-seitigen Datenbank-Anbindung verändert worden. Zum anderen wurde die close-Anweisung zum Schließen der DatenbankAnbindung entfernt.
Laden der Java-Klassen in die Datenbank
Um eine Java-Klasse in einer OracleJVM-Umgebung zu starten, muss diese zunächst in ein Datenbank-Schema geladen werden. Dabei sind folgende Dateiarten akzeptiert:
- Java-Sourcecode-Datei (*.java)
- Java-Class-Datei (*.class)
- Java-Ressource-Datei (*.jar bzw. *.zip)
Wird eine Java-Sourcecode-Datei in ein Datenbank-Schema geladen, so wird diese implizit mit dem in
der Datenbank verfügbaren Java-Kompiler in eine Java-Class-Datei übersetzt. Mit der folgenden
Anweisung wird eine Java-Klasse Jora in ein Datenbank-Schema MF geladen:
loadjava -user mf/mf@orcl10 -resolve -verbose C:\java\Jora.class
Die Option –resolve des loadjava-Kommandos besagt, dass nach dem Laden und Kompilieren von
©2005
Java-Klassen die Verfügbarkeit der abhängigen Java-Klassen überprüft werden soll. Die Option
–verbose aktiviert die Ausgabe der Meldungen auf dem Bildschirm, während die Klassen in die
Datenbank hochgeladen werden.
Alternativ zum loadjava-Kommando lässt sich das DBMS_JAVA-Paket verwenden. Dieses Paket
verfügt über Prozeduren, mit denen unter anderem Java-Klassen in die Datenbank geladen und aus
der Datenbank entfernt werden können. Mit dem folgenden Kommando wird eine Jora-Klasse in das
Datenbank-Schema MF der ORCL10-Datenbank geladen:
exec dbms_java.loadjava(
'-user mf/mf@orcl10 -resolve -verbose C:\java\Jora.class')
Voraussetzung für den Ladevorgang mit dem DBMS_JAVA-Paket ist allerdings das Leserecht des
Datenbank-Benutzers auf die zu ladende Datei. In der OracleJVM-Umgebung wird der Zugriff auf
Ressourcen mit einer sogenannten Java-Policy-Tabelle sichergestellt. Diese Tabelle gehört dem
Benutzer SYS und kann über die Views DBA_JAVA_POLICY und USER_JAVA_POLICY abgefragt
werden. Mit dem folgenden Kommando wird dem Benutzer MF ein Leserecht auf alle in dem
Verzeichnis C:\java vorhandenen Dateien erteilt:
exec dbms_java.grant_permission(
'MF','java.io.FilePermission','C:\java\*','read')
Bei der Angabe des Verzeichnisses kann mit der Syntax C:\java\- festgelegt werden, dass das
Leserecht auch noch für die im Verzeichnis vorhandenen Unterverzeichnisse gelten soll.
Die nachfolgende Abbildung veranschaulicht das Laden von Java-Klassen in eine Oracle-Datenbank.
Abb. 1: Laden von Java-Klassen in eine Oracle-Datenbank.
©2005
Java-Klassen aus der Datenbank entfernen
Wird eine Java-Klasse in der Datenbank nicht mehr benötigt, so kann diese mit dem dropjavaKommando aus der Datenbank entfernt werden. Das folgende Kommando entfernt die Jora-Klasse
aus der ORCL10-Datenbank:
dropjava -user mf/mf@orcl10 -verbose Jora
oder
exec dbms_java.dropjava('-user mf/mf@orcl10 -verbose Jora')
Ausblick
In der nächsten Ausgabe werden unter anderem das Resolving-Konzept und die Veröffentlichung von
Java-Klassen in der Datenbank erläutert sowie einige Anwendungsmöglichkeiten von Java Stored
Procedures vorgestellt.
Literaturhinweise
- Oracle und Java, Datenbankentwicklung für E-Commerce-Anwendungen, Elion Bonazzi,
Glenn Stokol, Markt &Technik Verlag, 2002
- Unleash the Power of Java Stored Procedures, Oracle Corporation, http://otn.oracle.com/,
2002
- Simplify with Java Stored Procedures, Oracle Corporation, http://otn.oracle.com/, 2004
- Oracle10g, Java Developer's Guide Release 1 (10.1), Oracle Corporation, 2004
Kontakt:
Markus Fiegler
[email protected]
©2005
Herunterladen