Seit jeher steht Java als plattformunabhängige Programmiersprache zwischen den Welten der verschiedenen Computersysteme. Aber gerade diese Tatsache hat dazu beigetragen, dass eine Reihe von übergreifenden Standards geschaffen wurden, um sich mehr und mehr von der Plattformbindung zu lösen. Wer in seinen Java-Projekten auf XML, SQL oder LDAP setzt, findet in Castor ein Data-Bind ing-Framework, das alle Anforderungen dieser Bereiche vereint und ein optimales Zusammenspiel mit der Programmiersprache Java garantiert. Der folgende Artikel bietet eine einfache und verständliche Einführung in die Anwendung des Frameworks Castor.
Wer sich zur Aufgabe stellt, alle Funktionen des Castor Data-Binding-Frameworks in einem Satz zu nennen, wird daran vermutlich schnell scheitern. Bereits wer die Aufzählung der Überschrift zu diesem Artikel beachtet und Java-Objekte, XML-Dokumente, SQL-Tabellen und LDAP-Verzeichnisse kennt, wird schnell die große Funktionsvielfalt von Castor erahnen können. Zunächst lassen sich zwei grundlegende Bereiche des Frameworks unterscheiden:
- Java-XML-Bindung (Castor XML)
- Java-SQL/LDAP Persistence (Castor JDO, Castor DAX, Castor DSML)
Beide Punkte haben natürlich das Ziel der Abbildung von Datensätzen auf Java-Objekte. Hierzu erhalten Sie mit Castor vielfältige Möglichkeiten, denn als Datenquellen können XML-Dokumente, SQL-Tabellen und LDAP-Verzeichnisse dienen. Selbstverständlich lassen sich diese Anwendungsfelder auch sehr einfach verbinden. Im nachfolgenden Artikel werden wir uns ebenfalls an diese Aufteilung halten und im ersten Teil auf die XML-Funktionen im Framework Castor eingehen. Der zweite Teil geht anschließend detailliert auf die Verwendung von Castor mit RDBMS ein. Die angesprochenen Funktionen zum Zugriff auf LDAP-Verzeichnisse werden in einem gesonderten Artikel in den folgenden Ausgaben des Java-Magazins betrachtet.
Castor XML
Castor XML beschreibt zunächst allgemein den Teil von Castor, der sich mit der XML-Verarbeitung und der Abbildung von XML-Daten auf Java-Objekte beschäftigt. Dieser Teil des Frameworks lässt sich also als XML-Data-Binding-Tool beschreiben. Betrachten wir zunächst das Marshalling-Framework, welches Bestandteil von Castor XML ist. Hiermit erhalten Sie die Möglichkeit, Daten aus XML-Dokumenten in Java-Objekte bzw. Java- Objekte in XML-Dokumente zu überführen.
Bevor Castor jedoch einsatzfähig ist, müssen wir zunächst die Installation des Frameworks ansprechen. Die entsprechenden Schritte sind denkbar einfach, da Castor im Wesentlichen aus einer einzigen Jar-Datei besteht, die lediglich in den Classpath eingebunden werden muss, damit die Castor-Funktionen zur Verfügung stehen. Das entsprechende Jar-Archiv ist auf der Webseite des Castor-Projekts [1] www.castor.org zu finden.
Das Marshalling-Framework
Das Marshalling-Framework kommt für die Umwandlung von Java-Objekten in XML und den umgekehrten Weg zum Einsatz. Hierdurch erhalten Sie einen Ansatz der über die Fähigkeiten von SAX und DOM hinausgeht und die betreffenden Daten nicht strukturell, sondern lediglich inhaltlich verwaltet. Zum Erzeugen der XML-Dokumente brauchen in diesem Fall keine Strukturen von Hand erzeugt werden - dies bleibt dem Castor-XML-Framework überlassen. Am besten lässt sich dieses Prinzip an einem einfachen Beispiel erläutern, welches zunächst die Umwandlung eines Java-Objekts in ein entsprechendes XML-Dokument vornimmt.
Zunächst wird eine Java-Klasse benötigt, die ein Objekt in Form einer Klasse enthält, welches die zu speichernden Daten aufnimmt. Listing 1 zeigt hierzu eine Klasse mit dem Namen
Film, welche drei Informationen über Filme enthält. Hierzu zählen der Filmtitel, das Erscheinungsjahr und die Filmlänge.
Listing 1 public class Film implements java.io.Serializable
{
private String title = null;
private Integer laenge = new Integer(0);
private Integer jahr = new Integer(1900);
public Film ()
{
super();
}
public Film (String title)
{
this.title = title;
}
public void setTitle (String title)
{
this.title = title;
}
public String getTitle ()
{
return title;
}
public void setLaenge (Integer laenge)
{
this.laenge = laenge;
}
public Integer getLaenge()
{
return laenge;
}
public void setJahr(Integer jahr)
{
this.jahr = jahr;
}
public Integer getJahr()
{
return jahr;
}
}
Wichtig ist hierbei die Implementierung eines public-Konstruktors und die Verwendung von getter- und setter-Methoden. Diese Vorgehensweise erinnert stark an die Programmierung von Java-Beans, die der gleichen Konvention entspricht. Eine Instanz der Klasse kann nun dem Marshaller übergeben werden, der sich anschließend um die Überführung der Datenstruktur in eine XML-Datei kümmert. Listing 2 verdeutlicht diese Vorgehensweise anhand eines Datensatzes vom Typ Film.
Listing 2 public void Marshal()
{
try
{
FileWriter writer = new FileWriter(new File(filme.xml));
Film film = new Film();
film.setTitle(Das schwarze Schaaf);
film.setJahr(new Integer(1960));
film.setLaenge(new Integer(90));
Marshaller.marshal(film, writer);
} catch (Exception e) {
e.printStackTrace();
}
}
Die Methode
marshal aus Listing 2 legt zunächst ein Objekt vom Typ FileWriter an. Dem Konstruktor wird hierbei der Name der XML-Datei übergeben, in die später der Datensatz des Films geschrieben werden soll. Ein Objekt vom Typ Film wird anschließend angelegt und mit den entsprechenden Daten gefüllt. Hierbei wird auf die setter-Methoden der Klasse
Film zurückgegriffen. Der Aufruf des Marshallers mittels
Marshaller.marshal(film, writer) kann nun erfolgenden. Hierzu müssen Sie wissen, dass die Klasse
Marshaller aus dem Package
org.exolab.castor.xml stammt. Hierzu muss das JAR-Archiv von Castor natürlich in den Classpath eingebunden werden. Die Methode
marshal erfordert die Übergabe von zwei Parametern. Zum einen wird das Objekt zur Speicherung übergeben (im Beispiel
Film) und zum anderen ein Objekt vom Typ FileWriter. Als Ausgabe sollte die Datei
filme.xml nun folgenden Inhalt aufweisen:
<?xml version="1.0"?>
<movie>
<title>Das schwarze Schaaf</title>
<jahr>1960</jahr>
<laenge>90</laenge>
</movie>
Mit diesem Beispiel lässt sich sehr gut verdeutlichen, dass sich die Anwendung des Castor-Frameworks sehr einfach gestaltet und praxistauglich ist. Der umgekehrte Weg lässt sich ebenso einfach durchführen und wird als Unmarshalling bezeichnet. Hierzu werden wir im Folgenden ein Objekt vom Typ Film aus der eben erzeugten XML-Datei generieren. Anstelle eines FileWriters wird in diesem Fall ein FileReader-Objekt eingesetzt, um die Datei
filme.xml einlesen zu können:
FileReader reader = new FileReader(new File(filme.xml));
Die Klasse
Unmarshaller aus dem Package
org.exolab.castor.xml kann nun verwendet werden, um ein Film-Objekt aus der XML-Datei anzufordern. Hierzu wird erneut auf eine statische Methode dieser Klasse zugegriffen:
Film film = (Film)Unmarshaller.unmarshal(Film.class, reader);
Steuern des Mappings
Der letzte Abschnitt hat Ihnen nun gezeigt, wie einfach die Übertragung von Daten zwischen Java-Objekten und XML-Dokumenten ist. Wir greifen mit der Marshaller- und Unmarshaller-Funktion bei den vorherigen Beispielen auf die Standardeinstellung von Castor zurück. Hierbei nehmen wir keinen Einfluss auf den Mapping-Vorgang und verlassen uns auf die Vorgaben von Castor. Wie Sie sich vielleicht vorstellen können, bietet das Castor-Framework auch in diesem Punkt Möglichkeit zur Anpassung. Alle gewünschten Einstellungen zur Transformation, die vom Standardverhalten Castors abweichen, werden in einer Mapping-Datei hinterlegt.
Die Mapping-Datei muss dem Marshaller durch die Methode
setMapping(Mapping mapping) mitgeteilt werden. Hierzu legen Sie zunächst ein Objekt vom Typ Mapping an (Listing 3).
Listing 3 ...
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
...
Mapping mapping = new Mapping();
try
{
...
mapping.loadMapping( "mapping.xml" );
Marshaller marshaller = new Marshaller(new OutputStreamWriter(System.out));
marshaller.setMapping(mapping);
marshaller.marshal(...);
} catch (MappingException mp)
{
...
}
...
Beachten Sie, dass beim Umgang mit Mapping-Objekten eine Exception vom Typ
MappingException ausgelöst werden kann, die von Ihrem Programm abgefangen werden muss. Die Mapping-Datei (im Beispiel
mapping.xml) wird durch die Methode
loadMapping (String file) geladen und mit dem entsprechenden Mapping-Objekt verbunden. Listing 3 zeigt die Verwendung einer Mapping-Datei durch einen Marshaller. Ähnlich einfach gestaltet sich die Verwendung von Mapping-Files in Kombination mit einem Unmarshaller. Hierbei wird die Mapping-Datei beim Konstruktoraufruf übergeben:
Unmarshaller unmar = new Unmarshaller(mapping);
Bisher haben wir lediglich die Anwendung einer Mapping-Datei betrachtet, jedoch keine Erläuterung zum Erstellen und zur Syntax einer solchen Datei gegeben. Dies wird im folgenden Abschnitt nachgeholt.
Aufbau von Mapping-Dateien
Wie Sie bereits im Beispielprogramm gesehen haben, handelt es sich bei der Mapping-Datei um ein XML-Dokument. Der Aufbau ist sehr einfach gehalten und klar gegliedert. Das Root-Element der Mapping-Beschreibung ist grundsätzlich das Element
>mapping/>. Innerhalb dieses Root-Elements können verschiedene Angaben gemacht werden, dazu zählen:
- eine Beschreibung mittels des Elements
- die Einbindung weiterer Mapping-Dateien durch das Element
- Klassenbeschreibungen durch
Hieraus ergibt sich folgende Struktur der Mapping-Datei:
<?xml version=1.0?>
<mapping>
<description> </description>
<include href=mapping2.xml\>
<class name=A>
</class>
<class name=B>
</class>
</mapping>
Das Element
erfordert nun besondere Aufmerksamkeit, da in diesem Abschnitt die grundlegenden Einstellungen zur Transformation der Java-Objekte hinterlegt werden. Zunächst wird durch das Attribut
name der Name der Klasse festgelegt. (Für weitere Möglichkeiten der Attribute werfen Sie bitte einen Blick in das Castor-Handbuch.)
Innerhalb des
-Elements können nun alle Informationen zum Mapping einer bestimmten Klasse untergebracht werden. Zunächst ist über das Element
festzulegen, wie das XML-Element benannt werden soll, das die aktuelle Klasse repräsentiert. Die Eigenschaften einer Klasse werden anschließend über
-Elemente in die Mapping-Informationen aufgenommen. Um nun beispielsweise die Eigenschaft
Titel einer Klasse aufzunehmen, kann die Mapping-Datei wie folgt angepasst werden:
<class name=Film>
<map-to xml=film/>
<field name=Titel direct=true type=java.lang.String>
<bind-xml name=filmtitel node=attribute/>
</field>
...
</class>
...
Dieses Beispiel behandelt die Eigenschaft
Titel der Klasse
Film. Über das Attribut
name wird zunächst der Name der Klasseneigenschaft übergeben und das Attribut
direct informiert Castor schließlich noch darüber, dass es sich bei
Titel um ein public-Objekt handelt, welches direkt benutzt werden kann. Castor wird somit keine getter- und setter-Methoden anlegen. Der Typ des Objekts wird durch das Attribut
type festgelegt. Hierbei kommt der vollständige Java-Klassenname zum Einsatz. Für die gebräuchlichsten Java-Klassen stehen außerdem Abkürzungen zur Verfügung, die anstelle des kompletten Klassennamens eingesetzt werden können. Hierzu finden Sie in der Castor-Dokumentation und auf der Castor-Homepage weitere Informationen.
Innerhalb des
field-Elements legen Sie weiterhin über
>bind-xml/> fest, wie das beschriebene Feld der Klasse in die XML-Datei übertragen werden soll. Das Attribut
name legt den Namen innerhalb des XML-Dokuments fest und
node definiert, ob die Darstellung als Attribut oder Child-Element erfolgen soll. Dazu können die Werte
attribute und
element übergeben werden.
Source-Generator
Im letzten Abschnitt haben Sie nun die Möglichkeiten des Mappings in Castor kennengelernt. Mapping beschäftigt sich grundsätzlich mit der Transformation von Java-Objekten zu einer XML-Struktur. Wie Sie sicherlich wissen, kann jede XML-Datei durch ein entsprechendes Schema validiert werden. Castor bietet mit dem eingebauten Source Code-Generator die Möglichkeit, aus einem XML-Schema eine Java-Klasse zu generieren. Verdeutlichen lässt sich die Benutzung des Source Code-Generators an einem einfachen Aufruf über die Kommandozeile:
java org.exolab.castor.builder.SourceGenerator -i schema.xsd -package de.foo
Dieser Aufruf analysiert zunächst die durch den Parameter
-i übergebene Schema-Datei und generiert anschließend aus diesen Informationen die benötigten Klassen. Alle Klassen befinden sich anschließend im
Package de.foo. Natürlich können die neu generierten Klassen mittels
javac problemlos kompiliert werden.
Wenn man die Funktionsweise des Source Code-Generators betrachtet, stellt sich natürlich die Frage, in welcher Weise die im Schema enthaltenen Funktionen ausgewertet werden, um die benötigten Informationen für eine Java-Klasse zu erhalten. Castor stellt Ihnen zwei unterschiedliche Methoden zur Klassengenerierung zur Verfügung. Zum einen kann der Source-Generator in Verbindung mit der so genannten
element'-Methode verwendet werden und zum anderen kann die
type'-Methode zum Einsatz kommen. Zunächst betrachten wir die
element'-Methode. Jeder top-level
complexType des Schemas wird bei dieser Methode in eine abstrakte Klasse transformiert. Es werden keine Klassen für
simpleType-Einträge erstellt. Diese Vorgehensweise lässt sich am besten an einem einfachen Beispiel verdeutlichen. Zunächst betrachten wir im folgenden Listing eine Schema-Datei:
<?xml version=1.0?>
<schema xmlns=http://www.w3.org/2000/10/XMLSchema
targetNamespace=http://www.xyz.de/castor>
<complexType name=Klassenname>
<sequence>
<element name=foo1 type=string/>
<element name=foo2 type=string/>
</sequence>
</complexType>
</schema>
Das Schema legt zunächst einen
complexType fest, der als Parameter den Namen der zu generierenden Klasse enthält. Innerhalb des
complexType nimmt das Element
die Elemente auf, die später in Eigenschaften (Variablen) der Klasse überführt werden können. Hierbei werden jeweils die Parameter
name und
type übergeben, die Informationen zum Typ und zum Namen der Klasseneigenschaft enthalten.
Die Klasse, die aus diesem Schema nach der Generierung mit der
element'-Methode entstehen würde, ist in Listing 4 abgedruckt.
Listing 4 import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import org.exolab.castor.xml.*;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;
import org.xml.sax.DocumentHandler;
public abstract class Klassenname implements java.io.Serializable {
private java.lang.String _foo1;
private java.lang.String _foo2;
public Klassenname() {
super();
} //-- Klassenname()
public java.lang.String getFoo1()
{
return this._foo1;
} //-- java.lang.String getFoo1()
public java.lang.String getFoo2()
{
return this._foo2;
} //-- java.lang.String getFoo2()
public boolean isValid()
{
try {
validate();
}
catch (org.exolab.castor.xml.ValidationException vex) {
return false;
}
return true;
} //-- boolean isValid()
public abstract void marshal(java.io.Writer out)
throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException;
public abstract void marshal(org.xml.sax.DocumentHandler handler)
throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException;
public void setFoo1(java.lang.String foo1)
this._foo1 = foo1;
} //-- void setFoo1(java.lang.String)
public void setFoo2(java.lang.String foo2)
{
this._foo2 = foo2;
} //-- void setFoo2(java.lang.String)
public void validate()
throws org.exolab.castor.xml.ValidationException
{
org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();
validator.validate(this);
} //-- void validate()
}
Die generierte Klasse setzt die beiden Element-Deklarationen der Schema-Datei als Variablen um, die jeweils mit den entsprechenden getter- und setter-Methoden ausgestattet sind. Außerdem werden die entsprechenden Methoden für den Marshaller als
abstract deklariert. Die Klasse selbst wird ebenfalls als
abstract deklariert. Dieses Verhalten lässt sich leicht ändern, indem der Umwandlungstyp von
element' auf
type' geändert wird. Hierzu müssen Sie eine Zeile der Datei
castorbuilder.properties ändern. Suchen Sie innerhalb dieser Datei die Zeile
org.exolab.castor.builder.javaclassmapping=element
und ändern Sie den Wert auf
type. Nun erhalten Sie eine implementierte Klasse, welche ohne abstract- Komponenten auskommt.
Java Data Object API
Wie eingangs besprochen, gehen wir nun zum zweiten Teil dieses Beitrags über und sehen uns - nach der Betrachtung der Castor XML-Funktionen - die Datenbankunterstützung mittels Java Data Objects an. Zunächst gibt es hierbei zwei unterschiedliche Anwendungsfälle zu unterscheiden: eine Datenbankverbindung kann in einer gewöhnlichen Client-Applikation vorkommen oder in einem J2EE Server-Umfeld. Im ersten Anwendungsfall muss eine Verbindung zur Datenbank mit Hilfe von JDBC von Hand aufgebaut werden. J2EE-Applikationen haben den Vorteil über JNDI Datenbankkonfiguration erfragen zu können. Somit brauchen hier keine Verbindungsparameter von Hand eingegeben werden. In Verbindung mit der Anwendung von Datenbankapplikationen bietet die J2EE-Plattform natürlich noch zahlreiche weitere Vorteile, auf die wir an dieser Stelle aber nicht weiter eingehen wollen. Vielmehr soll die weitere Betrachtung auf die Fähigkeiten des Castor-Frameworks in Verbindung mit den oben beschriebenen Anwendungsfällen gelenkt werden.
Java Data Objects übernehmen nun das Mapping von Java-Objekten zu SQL-Tabellen. Die Funktionsweise besitzt zudem viele Parallelen zum zuvor besprochenen XML-Mapping. Sie brauchen sich nicht um die Struktur der Java-Objekte zu kümmern und die Eigenschaften der Klasse einzeln von Hand auf die Datenbanktabelle abzubilden. Diese Aufgabe übernimmt die JDO-Funktion von Castor automatisch. Hierbei ist die persistente Speicherung der Objekte zentrale Aufgabe.
Persistente und transitorische Objekte
Bevor wir uns nun komplett auf die Programmierung mittels JDO konzentrieren, klären wir zunächst einmal den Unterschied zwischen persistenten und transitorischen Objekten. Ein Optimalfall eines Datenbankmappings ist dann gegeben, wenn es sich um eine persistente Speicherung von Objekten handelt. Dies bedeutet, dass die in der Datenbank abgelegten Daten zu jedem Zeitpunkt mit den Daten des Objekts übereinstimmen müssen. Dieser Zustand kann insbesondere bei commit, rollback oder update-Befehlen an die Datenbank nicht mehr zutreffen. Die Objekte gehen dann in einen transitorischen Zustand über.
Öffnen einer JDO-Datenbank-Verbindung
Das Öffnen einer JDO-Datenbank-Verbindung ist mit wenigen Schritten vollzogen. Es werden die Klassen
org.exolab.castor.jdo.JDO und
org.exolab.castor.jdo.Database benötigt. Hierzu folgendes Listing:
JDO jdo;
Database db;
jdo = new JDO();
jdo.setDatabaseName(mydb);
jdo.setConfiguration(dbconf.xml);
jdo.setClassLoading(getClass().getClassLoader());
db = jdo.getDatabase();
db.begin();
db.commit();
db.close();
Zunächst wird je ein Objekt vom Typ JDO und Database angelegt. Die Instanz des JDO-Objektes wird anschließend über den Aufruf der Methoden
setDatabaseName(String str) und
setConfiguration(String str) konfiguriert. Hier legen Sie Informationen zur Datenbankverbindung ab, die anschließend dazu benutzt werden können, eine Datenbankverbindung, die durch ein Objekt vom Typ Database repräsentiert wird, zu erhalten. Hierzu dient Ihnen die Methode
jdo.getDatabase(). Das Beispiel zeigt, dass die Datenbankverbindung lediglich durch einen Verweis auf eine XML-Datei beschrieben wird. Im voran gegangenen Listingbeispiel ist dies die Datei
dbconf.xml. Der folgende Abschnitt wird sich nun mit der Syntax dieser Datei beschäftigen und auf die Möglichkeiten der Konfiguration eingehen.
Datenbank-Konfiguration
Am besten lässt sich die Vorgehensweise der Konfiguration an einer einfachen Beispieldatei erkennen. Folgendes Listing zeigt hierzu eine Konfigurationsdatei für eine Oracle-Datenbank.
<database name="media" engine="oracle">
<driver class-name="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@machine:post:SID">
<param name="user" value="sebastian" />
<param name="password" value="media" />
</driver>
<mapping href="film.xml" />
<mapping href="buch.xml" />
<mapping href="cd.xml" />
</database>
<font></font>
Bei der Konfigurationsdatei handelt es sich um ein XML-Dokument mit dem Root-Element
. Hierbei werden die beiden Parameter
name und
engine übergeben.
name übergibt an dieser Stelle lediglich den Namen der Datenbank und
engine legt den Typ der Datenbank fest (im Beispiel eine Oracle 7 oder Oracle 8- Datenbank). Die Werte, die für das Attribut
engine zur Verfügung stehen, listet Tabelle 1 auf.
Nach der allgemeinen Einstellung der verwendeten Datenbank müssen nun die Treiber und die Verbindungsparamter festgelegt werden. Dies geschieht innerhalb des Elementes
. Als Parameter werden bei diesem Element der Klassenname des Treibers durch
class-name und die zugehörige URL durch
url übergeben. Weiterhin müssen für den Zugang durch das Element
>param> zwei zusätzliche Parameter übergeben werden. Dies sind zum einen der gültige Benutzername und zum anderen das zugehörige Passwort. Beachten Sie, dass dieses Vorgehen nur auf eine Oracle-Datenbank zutrifft. Wir sehen uns im Folgenden deshalb ein weiteres Beispiel für die Einstellungen zu einer PostgreSQL-Datenbank an. Schließlich befindet sich noch der Verweis auf die eigentlichen Mapping-Dateien innerhalb des XML-Dokuments. Eingeleitet durch das Element
mapping übergibt der Parameter
href die hierzu benötigte URL.
OQL
Um nun eine Anfrage an die zuvor konfigurierte Datenbank zu stellen, ist ein SQL-Statement sicherlich nicht das Mittel der Wahl, da das Objekt-Mapping gerade den Sinn verfolgt, sich von der Darstellung der Daten als Tabelle zu lösen. Vielmehr ist an dieser Stelle eine Abfragesprache gefordert, die mit Java-Objekten umgehen kann und die Fähigkeit besitzt, auf dieser Basis Datenbankabfragen zu generieren. Wie Sie sich sicherlich denken können, existiert auch für diesen Bereich innerhalb des Castor-Frameworks eine Lösung: OQL.
Bei OQL handelt es sich um eine Objekt-basierte Abfragesprache, die sich sehr eng an die Syntax von SQL anlehnt und daher für Umsteiger optimal geeignet ist. Wer zuvor keine SQL-Statements kennen gelernt hat, wird aber ebenfalls keine Probleme besitzen den Grundgedanken dieser Sprache zu verstehen.
Grundlegende Klassen für die Arbeit mit OQL in Castor sind
OQLQuery und
QueryResult. Ein
OQLQuery-Objekt ist sehr einfach über ein zuvor angelegtes Database-Objekt zu initialisieren:
OQLQuery myquery;
myquery = db.getOQLQuery(SELECT f FROM Film f WHERE f.preis = $20 );
Der Methode
getOQLQuery wird ein String übergeben, der die Anfrage darstellt. Der Hauptunterschied zu SQL ist hierbei die Tatsache, dass als Basis ein Objekt (im Beispiel das Objekt
Film) und dessen Eigenschaften (
preis) dienen. Ist erst einmal die Anfrage erstellt und in Form des OQLQuery-Objektes vorhanden, kann nun das Ergebnis mit Hilfe der Methode
execute() erfragt werden. Rückgabewert ist in diesem Fall ein
QueryResult. QueryResult result = myquery.execute();
Eine einfache Schleife reicht anschließend aus, um die Resultate der Reihe nach zu durchlaufen.
while (result.hasMore())
{
= result.next();
}
Wie Sie Objekte aus einer Datenbank erhalten, haben Sie nun gesehen. Was ist aber zu tun, um neue Objekte in eine Datenbank aufzunehmen oder aus dem Datenbestand zu entfernen? Auch diese Aufgabe ist denkbar einfach und über zwei einfache Methoden der Klasse
Database realisiert:
create(java.lang.Object) und
remove(java.lang.Object). Hierbei wird jeweils das Objekt übergeben, mit dem die jeweilige Operation durchgeführt werden soll. Mittels dieser Methoden können die Objekte zwischen den Zuständen transitorisch und persistent überführt werden.
Fazit
Dieser Artikel hat einen ersten Einblick in das Framework Castor gegeben. Sie werden sicherlich festgestellt haben, dass die Funktionen, die Castor bietet, sehr vielfältig sind und für zahlreiche Anwendungsgebiete Lösungen bereit halten. Auf der Basis von Java ebnet Castor den einheitlichen Weg zu verschiedenen Standards der Datenspeicherung. Das zentrale Anwendungsgebiet des Object-Mappings wird durch eine Reihe von Zusatzfunktionen abgerundet, die Castor einzigartig erscheinen lassen. Gerade im Bereich der objektorientierten Programmierung ist es von zentraler Bedeutung bei der Verwaltung von großen Datenmengen nicht die Objektorientierung zu verlassen. Eine einheitliche Struktur wird wesentlich zu der Effektivität einer Anwendung beitragen. Castor gibt Ihnen alle Mittel mit auf den Weg, die Sie für die Lösung dieser Probleme brauchen.
Wie eingangs erwähnt, ist dieser Beitrag noch nicht auf Anwendungsfälle des Castor-Projekts in Verbindung mit LDAP-Verzeichnissen eingegangen. Zu diesem Thema finden Sie einen eigenen Artikel in einer der nächsten Ausgaben des
Java Magazins.
Links und Literatur
[1]
www.castor.org