Diplomarbeit: Anbindung objektorientierter Software an

Werbung
Diplomarbeit:
Anbindung objektorientierter Software
an objektrelationale Datenbanken
Malte Finsterwalder
8. Oktober 2002
Bundesstraße 74
20144 Hamburg
Matrikelnummer: 4824574
Betreuer: Prof. Dr. Heinz Züllighoven
Universität Hamburg, Fachbereich Informatik,
Arbeitsbereich Softwaretechnik
Erklärung
Hiermit versichere ich, diese Arbeit selbständig und unter ausschließlicher
Zuhilfenahme der in der Arbeit aufgeführten Hilfsmittel erstellt zu haben.
Hamburg, den 8. Oktober 2002
Malte Finsterwalder
Bundesstraße 74
20144 Hamburg
Betreuung:
Prof. Dr. Heinz Züllighoven (Erstbetreuer)
Prof. Dr. Florian Matthes (Zweitbetreuer)
Prof. Dr. Heinz Züllighoven
Arbeitsbereich Softwaretechnik (SWT)
Fachbereich Informatik
Universität Hamburg
Vogt-Kölln-Straße 30
D-22527 Hamburg
Prof. Dr. Florian Matthes
Arbeitsbereich Softwaresysteme (STS)
Forschungsschwerpunkt 4 (IuK Technologie)
Technische Universität Hamburg-Harburg
Harburger Schloßstr. 20
D-21073 Hamburg
II
Inhaltsverzeichnis
1 Einleitung
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Fragestellung . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Grundlagen
2.1 3-Schichten-Architektur . . . . . . . . . . . . . . . . .
2.1.1 WAM-Service-Architektur . . . . . . . . . . .
2.2 Alternative Technologien . . . . . . . . . . . . . . . .
2.2.1 Relationale Datenbanken und Mapping-Tools
2.2.2 Objektorientierte Datenbanken . . . . . . . .
2.2.3 Enterprise Java Beans . . . . . . . . . . . . .
2.3 Auswertung . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Konzeption
3.1 Objektorientiertes Modell . . . . . . . . . . . . . . . . .
3.2 Relationales Modell . . . . . . . . . . . . . . . . . . . . .
3.2.1 Vor- und Nachteile des relationalen Modells . . .
3.3 Diskrepanzen zwischen den Modellen . . . . . . . . . . .
3.3.1 Anpassungen am relationalen Modell . . . . . . .
3.3.2 Anpassungen am objektorientierten Modell . . . .
3.4 Objektrelationale Datenbanken . . . . . . . . . . . . . .
3.4.1 Objektrelationales Modell . . . . . . . . . . . . .
3.4.2 Vor- und Nachteile des objektrelationalen Modells
3.5 Auswertung . . . . . . . . . . . . . . . . . . . . . . . . .
4 Umsetzung
4.1 SQL:1999-Standard . . . . . . . . . . . . . . . .
4.2 SQL:1999 Beispiel . . . . . . . . . . . . . . . . .
4.3 SQLj - objektrelationale Datenbanken und Java
4.4 Auswertung . . . . . . . . . . . . . . . . . . . .
III
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
2
2
.
.
.
.
.
.
.
5
5
6
9
10
12
17
20
.
.
.
.
.
.
.
.
.
.
23
23
26
29
30
34
35
36
36
39
41
.
.
.
.
43
44
45
56
57
5 Konstruktion
5.1 Datenbankmodellierung . . . .
5.1.1 Modellierungsrichtlinien
5.2 Beschreibung des Prototyps . .
5.3 Auswertung . . . . . . . . . . .
6 Schlussfolgerungen und Ausblick
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
63
63
67
68
77
79
Anhang
83
Abbildungsverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . 83
Tabellenverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Literaturverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
IV
Danksagung
Bekanntermaßen entsteht eine Diplomarbeit nicht von alleine und ich hatte
das Glück, sehr viel Unterstützung zu erhalten. Namentlich möchte ich einige
Personen erwähnen, ohne die diese Diplomarbeit nicht zustande gekommen
wäre:
Mein ganz besonderer Dank gilt Prof. Heinz Züllighoven für die Betreuung
dieser Diplomarbeit. Auch Prof. Florian Matthes danke ich für die Zweitbetreuung dieser Arbeit. Ich danke Stefan Roock für seine konstruktive Kritik,
sowie für zahlreiche gute und nützliche Anregungen.
Meiner Frau Silke Finsterwalder danke ich für ihren Zuspruch und ihr Engagement. Mit viel Geduld hat sie mich bei der Erstellung der Arbeit begleitet
und mir geholfen, die Barrieren beiseite zu schaffen, die im Weg waren. Danke
auch für unzählige Korrektur- und Verbesserungsvorschläge.
Besonderer Dank gilt auch Bastiaan Harmsen. Er hat mir geholfen, die dicksten Mauern zu durchbrechen, die sich mir beim Anfertigen dieser Arbeit in
den Weg stellten. Außerdem hat er die Arbeit wieder und wieder gelesen und
hilfreiche Kritik und Anregungen geben.
Auch allen anderen Beteiligten vielen Dank!
V
VI
Kapitel 1
Einleitung
1.1
Motivation
Viele Softwaresysteme müssen mit mehr oder minder großen Datenmengen
umgehen. Daher sind Datenbanken ein integraler Bestandteil vieler großer
Softwaresysteme. Es hat sich herausgestellt, dass dabei ein flexibler Zugriff
auf die Daten besonders wichtig ist. Insbesondere sollen bestimmte Daten,
anhand zum Teil komplexer Kriterien, in der Menge aller Daten gefunden
werden.
In der Softwareentwicklung haben sich die objektorientierten Programmiersprachen durchgesetzt. In vielen Projekten werden inzwischen objektorientierte Programmiersprachen wie Java, C++ und Smalltalk eingesetzt. Die
objektorientierten Datenbanken konnten sich jedoch bisher nicht in gleichem Maße etablieren. Stattdessen werden in den meisten Anwendungen
relationale Datenbanken eingesetzt, die sich seit einigen Jahren aufgrund
ihrer Flexibilität und Leistungsfähigkeit durchgesetzt haben. Im Jahr 2000
hatten relationale Datenbanken am Markt einen Anteil von mehr als 80%
(vgl. [Database Advisor]).
Das relationale Modell unterscheidet sich jedoch wesentlich vom objektorientierten Modell. Der gemeinsame Einsatz von objektorientierten Programmiersprachen und relationalen Datenbanken bringt daher einige Probleme
mit sich, was zusätzlichen Aufwand bei der Erstellung der Software verursacht. So bieten die Programmiersprachen andere Modellierungsmöglichkeiten als die Datenbanken. Eine direkte und einfache Abbildung von den Objekten der Anwendung auf die Tabellen einer relationalen Datenbank (und
umgekehrt) ist nicht möglich.
Um dem entgegen zu wirken, wurden die relationalen Datenbanken um objektorientierte Konzepte zu den objektrelationalen Datenbanken erweitert.
1
Damit wird der Versuch unternommen, die objektorientierten Konzepte der
Programmiersprachen in die etablierten Datenbanken zu übernehmen. Die
Annäherung der beiden zugrunde liegenden Modelle von Programmiersprache und Datenbank soll den gemeinsamen Einsatz erleichtern.
Die objektrelationalen Datenbanken sind eine vielversprechende Lösung. Sie
sind eine kontinuierliche Weiterentwicklung bestehender Technologie. Die
neuen Konzepte werden schrittweise mit neuen Versionen in die bestehenden relationalen Datenbanken aufgenommen. Dadurch überträgt sich auch
der hohe Marktanteil der relationalen Datenbanken automatisch auf den der
objektrelationalen Datenbanken. Die bestehenden Erfahrungen können weiter genutzt werden, der zusätzliche Schulungsaufwand ist relativ gering.
1.2
Fragestellung
In dieser Arbeit wird untersucht, wie die Konzepte der Objektorientierung in
das relationale Datenmodell integriert werden. Darüber hinaus wird betrachtet, wie die neue Funktionalität genutzt werden kann und welche Auswirkungen dies auf die Erstellung der Software hat. Dabei steht die Entwicklung
großer, objektorientierter Softwaresysteme im Vordergrund.
Folgende Fragen stellen sich: Wie einfach lassen sich die neuen Konzepte in
die Software integrieren? Wie vergleichbar sind die Konzepte der Datenbanken mit denen der gängigen objektorientierten Programmiersprachen? Kann
ein bestehendes Objekt-Modell einer objektorientierten Software direkt in
die Datenbank übernommen werden, oder ist neben der Modellierung der
Software eine Datenmodellierung für die Datenbank nötig?
1.3
Vorgehen
Zuerst werden die bestehenden Diskrepanzen zwischen dem objektorientierten- und dem relationalen Modell herausgearbeitet. Daraus werden
mögliche Erweiterungen und Anpassungen abgeleitet, die diese Diskrepanzen
vermeiden, oder zumindest verringern.
Daraufhin wird das bestehende objektrelationale Modell untersucht, welches
objektorientierte Erweiterungen in das relationale Modell integriert. Das Zusammenspiel von objektorientiertem und objektrelationalem Modell wird dabei besonders beachtet.
Als nächstes wird der bestehende SQL:1999-Standard für objektrelationale
Datenbanken dargestellt (vgl. ISO Standard Nr. 9075). Zu den objektorientierten Erweiterungen dieses Standards gehören vor allem die Definition
2
von benutzerdefinierten, strukturierten Datentypen, das Binden von Methoden an diese Datentypen, sowie die Objektidentität und Referenzen zwischen
Objekten.
Ziel des Standards ist es, die Anwendungsentwicklung mit objektorientierten Programmiersprachen zu unterstützen. Insbesondere soll der Unterschied
zwischen der Modellierung der Software und der Modellierung der Daten in
der Datenbank verkleinert werden. Ebenso soll das Laden und Speichern von
Objekten erleichtert werden.
Das objektrelationale Modell des SQL:1999-Standards wird dem objektrelationalen Modell gegenübergestellt und anhand dessen bewertet. Auch hierbei
wird besonders das Zusammenspiel mit den objektorientierten Programmiersprachen betrachtet.
Die erarbeiteten Konzepte werden dann anhand eines prototypischen Beispiels praktisch umgesetzt. Damit wird exemplarisch gezeigt, wie eine konstruktive Umsetzung mit der verfügbaren Technik möglich ist und welche
Probleme damit verbunden sein können.
Zur Umsetzung der praktischen Elemente werden in dieser Arbeit die objektorientierte Programmiersprache Java und die IBM Datenbank DB2 verwendet.
3
4
Kapitel 2
Grundlagen
2.1
3-Schichten-Architektur
Bei der Erstellung großer Anwendungssysteme hat sich weitgehend eine so
genannte 3-Schichten-Architektur etabliert (vgl. [Fowler 02]). Dabei wird die
Geschäftslogik von der Präsentation und der Datenhaltung getrennt.
Die Präsentationsschicht regelt die Darstellung und Interaktion mit dem
Anwender. Sie greift für die eigentliche Bearbeitung auf die Geschäftslogik
zurück. Die Geschäftslogik wiederum greift zur persistenten Speicherung auf
die Datenhaltung zurück.
1. Schicht
Präsentation
2. Schicht
Geschäftslogik
?
?
3. Schicht
Datenhaltung
Abbildung 2.1: 3-Schichten Architektur
Diese Aufteilung ermöglicht es, die Geschäftslogik von den meist stark technisch beeinflussten Bereichen Präsentation und Datenhaltung zu isolieren.
Dies hat mehrere Vorteile:
• Dieselbe Geschäftslogik kann von verschiedenen Front-Ends aus genutzt
werden.
• Änderungen der Darstellung oder gar der verwendeten GUITechnologie beeinflussen die Geschäftslogik nicht.
5
• Ein Austausch der verwendeten Datenbank ist möglich.
• Die verwendete Datenbank hat kaum Einfluss auf den softwaretechnischen Entwurf der Geschäftslogik.
Außerdem ist die Änderungsrate in den drei Schichten häufig sehr unterschiedlich. Die Datenmodelle einer Datenbank ändern sich meist nur
sehr langsam. Insbesondere dann, wenn mehrere verschiedene Anwendungen
gleichzeitig auf demselben Datenmodell arbeiten, verursacht eine Änderung
im Datenmodell großen Aufwand, da alle Anwendungen angepasst werden
müssen.
Die Geschäftslogik ändert sich häufiger. Änderungen in diesem Bereich sind
immer dann nötig, wenn sich Änderungen im Anwendungsfeld ergeben.
Die Präsentation ändert sich ebenfalls häufig. Teilweise wird auch die Präsentationsschicht komplett ausgetauscht, um beispielsweise eine Anwendung, die
bisher über ein interaktives GUI verwendet wurde, über ein Web-Frontend
im Internet zur Verfügung zu stellen.
Änderungen in den verschiedenen Schichten haben unterschiedliche Ursachen
und ergeben sich daher zu unterschiedlichen Zeiten. Um den Aufwand in
Maßen halten zu können, ist eine weitgehende Isolation von Vorteil.
Bei größeren Software-Anwendungen kann es sinnvoll sein, die drei Schichten weiter zu unterteilen. Außerdem muss für jede Anwendung individuell
entschieden werden, welche Programmteile in welcher Schicht untergebracht
werden. Wenn verschiedene Schichten auf unterschiedliche Hardware verteilt
werden, kann auch dies eine konkrete Verteilung der Programmlogik beeinflussen. Die 3-Schichten-Architektur stellt also weniger ein hartes Kriterium,
als vielmehr eine grobe Richtlinie dar.
2.1.1
WAM-Service-Architektur
Der
Werkzeug & Material-Ansatz (WAM-Ansatz) beschreibt eine anwendungsorientierte Sichtweise auf die Softwareerstellung (vgl.
[Züllighoven et al. 98]). Das Ziel ist es, Software von hoher Gebrauchsqualität zu erstellen. Hohe Gebrauchsqualität wird dabei wie folgt charakterisiert
(vgl. [Züllighoven et al. 98], S. 4):
• Die Funktionalität des Systems orientiert sich an den Aufgaben aus dem Anwendungsbereich.
• Die Handhabung des Systems ist benutzergerecht.
6
• Die im System festgelegten Abläufe und Schritte lassen sich
je nach Anwendungssituation problemlos an die tatsächlichen Anforderungen anpassen.
Die zentrale Idee des Werkzeug & Material-Ansatzes ist, die Gegenstände
”
und Konzepte des Anwendungsbereichs als Grundlage des softwaretechnischen Modells zu nehmen.“ (vgl. [Züllighoven et al. 98], S. 4). Die Konzeption der Software richtet sich also stark nach dem Anwendungsbereich, für
den die Software erstellt wird. Insbesondere definiert der WAM-Ansatz Entwurfsmetaphern, die bei der Strukturierung des Anwendungsbereichs Hilfe
leisten. Dazu zählen vor allem: Werkzeug, Material, Automat, Fachwert und
Arbeitsumgebung.
Der WAM-Ansatz beschreibt darüber hinaus einen Satz von Konzeptionsund Entwurfsmustern, die den Entwickler bei der Softwareerstellung anleiten und unterstützen. Dazu zählen unter anderem Anleitungen zum Materialund Werkzeug-Entwurf sowie die Trennung von Interaktion und Funktionalität.
Die Trennung von Interaktion und Funktionalität ist eine Konkretisierung der
3-Schichten-Architektur. Die Präsentations-Schicht wird hier von der fachlichen Logik getrennt. Da WAM-Anwendungen häufig hochgradig interaktiv
sind, findet zwischen den beiden Schichten ein hoher Grad an Interaktion
statt. Daher werden beide Schichten meist auf demselben Client-Rechner
ausgeführt.
Im Jahre 2000 wurde zum WAM-Ansatz der Gedanke des fachlichen Service
hinzugefügt (vgl. [Otto, Schuler 2000]). Ein fachlicher Service kapselt eine
Geschäftsfunktionalität und stellt diese anderen Anwendungen als Dienstleistung zur Verfügung. Ein Client kann die Dienstleistung in Anspruch nehmen,
indem er einen Auftrag an den Service schickt.
Ein Beispiel für einen fachlichen Service könnte eine Routenplanung für Autofahrer sein. Der Client schickt dem Service einen Auftrag mit dem gewünschten Start- und Endpunkt der zu berechnenden Strecke. Der Service ermittelt
die Route und liefert das Ergebnis in einer geeigneten Form zurück.
Ein fachlicher Service wird ausschließlich über eine wohldefinierte Schnittstelle angesprochen und kapselt die interne Umsetzung. Dadurch helfen fachliche Services, ein komplexes Softwaresystem in verschiedene, fachlich zusammenhängende Teilbereiche zu zerlegen. Damit wird die Komplexität des
Gesamtsystems reduziert und eine bessere interne Struktur der Software erreicht.
7
Fachliche Services laufen zumeist auf einem Server und werden über RemoteZugriffe, z.B. mittels RMI oder CORBA, angesprochen. Sie haben dadurch Ähnlichkeit mit einem Applikationsserver, wie er auch bei der EJBArchitektur eingesetzt wird.
Ein weiterer Vorteil der Kapselung der Geschäftslogik in einem fachlichen Service besteht darin, dass sie daraufhin von verschiedenen Client-Anwendungen
genutzt werden kann. So können unterschiedliche Benutzungsschnittstellen
erstellt werden, ohne dass die zugrunde liegende Funktionalität mehrmals
entwickelt werden muss. Eine Desktop- und eine Web-Anwendung können so
beispielsweise denselben fachlichen Service verwenden.
Auch dies ist eine weitere Konkretisierung der 3-Schichten-Architektur. Die
Geschäftslogik wird hier nochmals strukturiert. Teile der Geschäftslogik, die
eine zusammenhängende Einheit bilden, werden in fachliche Services gekapselt. Dies sind zudem meist Teile, die von mehreren Anwendern und Anwendungen gleichzeitig genutzt werden sollen. Der restliche Teil der Geschäftslogik verbleibt auf dem Client-Rechner und greift auf die Dienste des fachlichen
Services zurück, um seine Aufgabe zu erfüllen.
In Abbildung 2.2 ist eine Darstellung dieser Architektur zu sehen.
2. Client
1. Client
Präsentation
Interaktion
Interaktion
?
?
Funktion
J
Geschäftslogik
?
Funktion
J
J
J
J
^ J
FS
FS
?
FS
Server
Datenhaltung
Abbildung 2.2: Architektur einer WAM-Anwendung
8
Es gibt Services, die Materialien speichern und verwalten ebenso wie solche,
die dies nicht tun. Materialverwaltende Services sind solche, die Materialien erstellen, dauerhaft speichern und einem Client für die Bearbeitung zur
Verfügung stellen. Zusätzlich werden häufig Funktionen zum Organisieren
und Verändern von Mengen von Materialien bereitgestellt. Damit bietet ein
materialverwaltender Service eine anwendungsfachliche Sicht auf einen Datenspeicher und abstrahiert von der zugrunde liegenden Speicherung. Dadurch wird die Datenhaltung von der Geschäftslogik getrennt. Die Datenhaltung wird im Service gekapselt und Materialien werden über explizite Zugriffe
am Service abgefragt, gespeichert und manipuliert.
Ein Client, der die Dienste des Service in Anspruch nimmt, braucht sich also
nicht um die technische Umsetzung zu kümmern. Insbesondere ist die Anpassung an die zugrunde liegende Speicher-Technologie im Service gebündelt. So
kann ein Austausch des Service durch einen anderen Service mit derselben
Schnittstelle die gesamte Anwendung auf eine andere Speicher-Technologie
umstellen.
2.2
Alternative Technologien
Für die persistente Speicherung bieten sich verschiedene Alternativen an. Mit
Abstand am weitesten verbreitet sind die relationalen Datenbanken. Diese
Datenbanken sind jedoch nicht gut an objektorientierte Programmiersprachen angepasst, da bei den beiden Technologien grundlegend unterschiedliche Konzepte zugrunde liegen. Im Kapitel 3.2 auf Seite 26 wird dies noch
genauer erläutert.
Dies macht sich auch durch einen hohen Aufwand bei der Erstellung der
Anwendung bemerkbar. Steve McClure gibt an, dass bis zu 25% des Programmieraufwandes allein für die Anbindung einer relationalen Datenbank
anfallen können (vgl. [McClure 97]).
Der entstehende Aufwand kann auf verschiedenen Wegen reduziert werden.
Eine Möglichkeit ist es, weiterhin relationale Datenbanken einzusetzen, den
Aufwand jedoch durch den Einsatz von zusätzlichen Tools zu verringern.
Dazu zählen vor allem die relationalen Mapping-Tools.
Steve McClure schlägt zur Reduzierung des Aufwandes die objektorientierten Datenbanken vor. Diese sind wesentlich besser an die objektorientierten
Programmiersprachen angepasst, wodurch wesentlich weniger Aufwand bei
einem gemeinsamen Einsatz entsteht.
9
Im Zusammenhang mit Java bietet sich zudem die Java-spezifische Technologie Enterprise Java Beans (EJB) an, die ebenfalls eine in großen Teilen
automatisierte persistente Datenhaltung zur Verfügung stellt.
Im Folgenden werden diese alternativen Technologien kurz vorgestellt und
eingeordnet.
2.2.1
Relationale Datenbanken und Mapping-Tools
Der Zugriff auf relationale Datenbanken aus objektorientierten Programmiersprachen heraus stellt in sehr vielen Softwareprojekten ein konkretes, konstruktives Problem dar. Es ist daher nicht verwunderlich, dass dieses Problem eine große Beachtung findet und eine große Anzahl von bestehenden
Lösungsansätzen existiert.
Wolfgang Keller hat mögliche konstruktive Techniken zusammengestellt, wie
man die Abbildung zwischen den relationalen Datenbanken und den objektorientierten Programmiersprachen gestalten kann und welche Faktoren die
nötigen Entscheidungen beeinflussen (vgl. [Keller 98]).
Es zeigt sich jedoch, dass diese Ansätze zum Teil mit großem Aufwand verbunden sind. Allein für die Erstellung einer Datenbank Zugriffsschicht gibt Wolfgang Keller, abhängig von den enthaltenen Funktionen
und der gewählten Umsetzung, einen Aufwand von 0,5 bis 35 PersonenJahre an (vgl. [Keller, Coldewey 97]). Darin ist jedoch noch keine Abbildung von den Objekten der Programmiersprache auf die Relationen der
Datenbank enthalten, was den komplexesten Teil der Abbildung darstellt
(vgl. [Coldewey, Keller 96]). Die geschilderte Zugriffsschicht ermöglicht es der
Anwendung lediglich, einfacher auf die Strukturen und Daten der Datenbank
zuzugreifen und zudem Optimierungen einzubauen. Vor allem wird dabei eine Entkopplung zwischen dem Datenbankdesign und dem Anwendungsdesign
angestrebt.
Um dies zu erreichen, wird eine Zwei-Schichten-Architektur aufgebaut. Die
obere, anwendungsnahe Schicht stellt Klassen bereit, um anwendungsfachlich auf die Daten zugreifen zu können. Die untere, datenbanknahe Schicht
setzt diese Zugriffe auf die Strukturen der Datenbank um. Datenbankzugriffe werden ausschließlich in der unteren Schicht durchgeführt, wodurch
die Anwendung vom Datenbankdesign weitgehend losgelöst ist. Anfragen an
die Datenbank sowie die Auswertung der daraus resultierenden Ergebnisse
werden wesentlich erleichtert. Zusätzlich werden noch Caching-Mechanismen
bereitgestellt, um die Geschwindigkeit zu steigern.
10
Ein weiterer Aspekt ist neben dem Entwicklungsaufwand das Laufzeitverhalten einer solchen Lösung. Die objektorientierten Programmiersprachen
verfügen über einige Modellierungsmöglichkeiten, die in den Datenbanken
nicht zur Verfügung stehen. Diese müssen dann in den Datenbanken mit Hilfskonstrukten nachgebildet werden (vgl. [Ambler 00b] und [Brown et al. 96]).
So müssen komplexe, geschachtelte Objekte erst zerlegt werden, bevor
sie in der Datenbank in mehreren Relationen gespeichert werden können.
Verknüpfungen zwischen Objekten müssen durch Fremdschlüsselbeziehungen nachgebildet werden, die bei der Abfrage der Daten kostspielige JoinOperationen erfordern. Für die Speicherung von Objekten, die in einer Vererbungsbeziehung stehen, schlägt Ambler verschiedene Techniken vor, die jeweils spezifische Vor- und Nachteile bezüglich Flexibilität, Speicherverbrauch
und Geschwindigkeit besitzen. In jedem Fall führen die verschiedenen Maßnahmen, die zur Nachbildung der fehlenden Funktionen eingesetzt werden,
zu einer Verschlechterung des Laufzeitverhaltens der Datenbankanbindung.
Es gibt Standardprodukte, die eine Objekt-Relationen-Abbildung zur Verfügung stellen. Diese so genannten Mapping-Tools können zwar den Entwicklungsaufwand reduzieren, aber auch hier leidet unter Umständen das Laufzeitverhalten. Zudem sind die Modellierungsmöglichkeiten durch die Tools
eingeschränkt. Es wird meist nicht die volle Mächtigkeit der Objektorientierung unterstützt. Außerdem sind die von den Produkten erzeugten Datenbankstrukturen teilweise schwer durchschaubar, da die Mapping-Tools die
Daten auf verschiedene Tabellen aufteilen und zusätzliche Verbindungs- und
Statustabellen einfügen. Ohne das Mapping-Tool ist der Zugriff auf die Daten dadurch erschwert. Häufig sollen jedoch verschiedene Anwendungen auf
die Daten zugreifen. Dabei ist nicht gewährleistet, dass alle diese Anwendungen dasselbe Mapping-Tool einsetzten können, z.B. weil die Anwendungen
in verschiedenen Programmiersprachen entwickelt werden. Außerdem sollen
die Daten häufig über die Lebenszeit der erstellten Software hinaus weiter benutzbar bleiben. Auch dies gestaltet sich schwierig, wenn die Datenbankstruktur unübersichtlich ist. Obendrein ist die Nutzung der verschiedenen Mapping-Tools nicht standardisiert, man bindet sich somit an einen
bestimmten Hersteller.
Vor- und Nachteile relationaler Mapping-Tools
Die Mapping-Tools kapseln die relationale Datenbank durch eine Zugriffsschicht. Die Abbildung von Objekten auf relationale Strukturen wird zum
größten Teil automatisch von den Tools abgewickelt. Dies verringert den
Aufwand bei der Erstellung der Software-Anwendung erheblich.
11
Die Mängel in der Datenbankanbindung können dadurch jedoch nicht behoben, sondern höchstens verborgen werden. Eine echte Integration der beiden
Modelle findet nicht statt. Die Mapping-Tools konzentrieren sich zudem auf
das objektorientierte Modell und versuchen dieses Modell in den relationalen
Datenbanken zu simulieren. Dazu werden die aus Sicht des objektorientierten
Modells fehlenden Elemente in der Zugriffsschicht überbrückt und nachgebildet. Eine Integration von relationalen Konzepten in den objektorientierten
Programmiersprachen findet nicht statt.
2.2.2
Objektorientierte Datenbanken
Eine mögliche Alternative für die Speicherung von Objekten sind die objektorientierten Datenbanken. Schon der Name lässt vermuten, dass diese Datenbanken für die Zusammenarbeit mit objektorientierten Programmiersprachen optimiert sind. In der Tat greifen die objektorientierten Datenbanken
die Konzepte der Objektorientierung auf.
Im Datenbankumfeld existiert jedoch teilweise ein unterschiedliches
Verständnis von diesen Konzepten. Dies liegt unter anderem darin begründet,
dass die persistente und lang anhaltende Speicherung von Objekten andere
Anforderungen stellt, als die kurzzeitige, transiente Verwendung von Objekten im Speicher. Außerdem sind die objektorientierten Datenbanken parallel
zu den objektorientierten Programmiersprachen entstanden. Die Konzepte
haben sich also zeitgleich und teilweise unabhängig voneinander entwickelt.
Leider gibt es, zumindest zum jetzigen Zeitpunkt, noch kein einheitliches
theoretisches Datenbankmodell für die objektorientierten Datenbanken, welches vergleichbar mit dem Relationenmodell für relationale Datenbanken
wäre. Ein mögliches Modell wird beispielsweise von Andreas Heuer beschrieben (vgl. [Heuer 97]).
Die am Markt befindlichen Datenbanken orientieren sich meist an eigenen
Modellen, die stärker auf die Praxis zugeschnitten sind. Sie sind dabei häufig
auf eine bestimmte Programmiersprache ausgerichtet und abgestimmt.
Um die Unterschiede zwischen den auf dem Markt befindlichen Datenbanken zu verringern, wurde im Jahre 1991 die Object Data Management
Group (ODMG) als Untergruppe der Object Management Group (OMG) gegründet. In dieser Gruppe haben sich viele Hersteller objektorientierter Datenbanksysteme zusammengeschlossen und sich zum Ziel gesetzt, einen Defacto-Standard für objektorientierte Datenbanken zu etablieren. Der ODMGStandard liegt in der aktuellen Version 3.0 vor (vgl. [ODMG]) und setzt sich
aus vier Teilen zusammen:
12
1. ODMG-Objektmodell
2. Object Definition Language (ODL)
3. Object Query Language (OQL)
4. ODMG-Sprachanbindungen für Smalltalk, C++ und Java
Im ODMG-Objektmodell werden die grundlegenden Begriffe definiert. Hier
ist beispielsweise festgehalten, was ein Objekt ist, was ein Typ ist und wie die
Eigenschaften und das Verhalten von Objekten beschrieben werden. Die Definitionen sind denen der objektorientierten Programmiersprachen sehr ähnlich.
Neben einigen Standard-Datentypen wird das allgemeine Konzept eines Typs
eingeführt. Ein Typ beschreibt die Struktur eines Objekts, wozu die Attribute, Beziehungen und Methoden zählen. Ein Typ wird dabei durch seine
Schnittstelle beschrieben und kann mehrere, unterschiedliche Implementationen besitzen. Der Begriff der Klasse wird, genauso wie bei den Programmiersprachen, als eine konkrete Implementation eines Typs eingeführt. Es ist zu
beachten, dass die Typ-Beschreibung mit der ODL oder einer sprachabhängigen Programming Language-ODL (PL-ODL) durchgeführt wird, wohingegen
die Implementation mit einer der unterstützen Programmiersprachen umgesetzt wird.
Objekte mit den gleichen Eigenschaften werden durch einen Typ zusammengefasst. Ein Objekt besitzt eine Identität und einen Zustand, der durch
Methodenaufrufe verändert werden kann. Neben der Identität eines Objekts,
kann jedem Objekt auch ein Name gegeben werden, der in der Datenbank
eindeutig ist. Über diesen Namen kann auf das Objekt zugegriffen werden.
Der Zustand wird in Attributen gespeichert, die entweder Werte oder andere Objekte aufnehmen können. Es gibt auch Collection-wertige Objekte, die
eine Menge von Objekten aufnehmen können. Dazu zählen List, Set, Bag,
Array und Dictionary. Darüber hinaus gibt es noch Beziehungen zu anderen Objekten, die sich von den Objekt-Attributen dadurch unterscheiden,
dass durch die Datenbank immer auch eine inverse Referenz aufgebaut wird.
Darüber hinaus werden Literale (Werte) definiert, die ihren Zustand nicht
verändern können.
Des Weiteren wird für ein erzeugtes Objekt der Begriff der Instance“ (Ex”
emplar) definiert. Jedes Objekt ist immer Exemplar von genau einer Klasse
und besitzt damit genau einen Typ. Ein Objekt kann seinen Typ zur Laufzeit
nicht mehr verändern, sondern behält ihn während seines gesamten Lebenszyklus bei. Auch dies verhält sich identisch zu den Programmiersprachen. Die
Menge aller erzeugten Objekte einer Klasse wird als Extension dieser Klasse
13
bezeichnet.
Objekte werden durch Factory-Methoden erzeugt. Beim Erzeugen wird angegeben, ob das Objekt transient oder persistent sein soll. Transiente Objekte
”
verbleiben unter der Kontrolle der Programmiersprachen und werden nicht
dauerhaft gespeichert, persistente Objekte werden dagegen unter der Verantwortung des Datenbanksystems langfristig gespeichert.“ (vgl. [Heuer 97],
S. 438).
Das Objektmodell definiert die Typvererbung genau so, wie es von den Programmiersprachen her bekannt ist. Bei der Typvererbung wird die Mehrfachvererbung unterstützt. Davon unterschieden wird die Implementationsvererbung, bei der jedoch keine Mehrfachvererbung unterstützt wird, um Konflikte
zu vermeiden.
Um auf die Objekte zuzugreifen, wurde im ODMG-Standard die Object
Query Language (OQL) definiert. Diese Sprache baut auf dem Select-Block
von SQL-92 auf, wurde jedoch um einige Konstrukte erweitert. So ist es
beispielsweise möglich, auf komplexe Objekte zuzugreifen, Methoden aufzurufen und von einem Objekt zu einem anderen zu navigieren. Die OQL ist
eine funktionale Sprache, die, im Gegensatz zu SQL, vollständig orthogonal
ist. Die einzelnen OQL-Befehle sind abstrakt definiert und besitzen mehrere mögliche Konkretisierungen. Eine ist die SQL-artige Konkretisierung,
die meistens gemeint ist, wenn von OQL die Rede ist. Die SQL-artige OQL
kann, ähnlich wie SQL selbst, von den Programmiersprachen nur über eine
Call-Schnittstelle genutzt werden und ist nicht in die Programmiersprachen
selbst integriert. Deswegen ist weder eine Syntaxprüfung noch eine Typinferenz zur Übersetzungszeit möglich. Daneben gibt es Ausprägungen, die an
die unterstützen Programmiersprachen angelehnt sind.
Die OQL unterstützt relationale, objekterzeugende und objekterhaltende Anfragen. Relationale Anfragen liefern Tupel mit Werten zurück. In einer Anfrage können auch Objekte eines bestehenden Typs erzeugt werden. Die objekterhaltenden Anfragen liefern die abgelegten Objekte als Ganzes zurück.
Anfragen können dabei auf alle Arten von Mengen ausgeführt werden. Dazu
zählen vor allem die Extension einer Klasse und Collection-wertige Objekte.
Im letzten Teil, den Sprachanbindungen, wird die Einbettung in eine konkrete Programmiersprache festgehalten. Darin wird unter anderem beschrieben,
wie das Typsystem der Programmiersprache mit dem der Datenbank zusammen arbeitet. Weiterhin werden Klassenbibliotheken definiert, die einen
bruchlosen Zugriff auf die Datenbank mit den Mitteln der Programmiersprache ermöglichen. Die verschiedenen Sprachanbindungen unterscheiden sich
14
sehr deutlich und sind auf die Möglichkeiten der jeweiligen Programmiersprache zugeschnitten.
Darüber hinaus wird eine Anwendungsarchitektur“ beschrieben. Diese legt
”
fest, wie eine Software erstellt wird, die eine objektorientierte Datenbank
verwendet. Die Software selbst wird in einer objektorientierten Programmiersprache verfasst. Die Objekttypen werden jedoch entweder in der sprachunabhängigen ODL, oder einer sprachabhängigen PL-ODL, definiert. Diese
Definition wird dann von einem Präprozessor in die tatsächliche Klassendefinition der Programmiersprache übersetzt. Gleichzeitig wird die Objektbeschreibung auch in der Datenbank abgelegt. Außerdem wird beim Linken der
Anwendung die Laufzeit-Umgebung der Datenbank in die Anwendung eingebunden. Daraufhin kann die Anwendung auf einer Datenbank arbeiten, die
genau die vom Präprozessor erzeugten Objektbeschreibungen enthält. Wenn
sich das Objektmodell in der Datenbank ändert, muss auch die Anwendung
neu kompiliert werden. Das Datenmodell in der Datenbank entwickelt sich
also synchron mit dem der Programmiersprache und kann nicht entkoppelt
werden.
Die ODMG unterscheidet zwei Stufen bei der Einhaltung des Standards:
ODMG-konform (ODMG-compliant) und ODMG-zertifiziert (ODMGcertified). Ein System ist bereits ODMG-konform, wenn es in einer der folgenden Komponenten ODMG-konform ist:
• Object Definition Language (ODL)
• Object Query Language (OQL)
• C++ Sprachanbindung
• Smalltalk Sprachanbindung
• Java Sprachanbindung
Die Aussage, ob ein System ODMG-konform ist oder nicht, stützt sich zudem
lediglich auf die Angaben der Herstellers. Die ODMG prüft also nicht, ob das
System die Anforderungen wirklich korrekt erfüllt.
Bei den ODMG-zertifizierten Systemen wird hingegen angegeben, bezüglich
welcher der oben aufgeführten fünf Komponenten das System zertifiziert wurde. Außerdem muss das System zuerst eine Test-Suite der ODMG durchlaufen, bevor es zertifiziert wird. Auf der Web-Seite der ODMG sind zum jetzigen
Zeitpunkt ausschließlich ODMG-konforme Systeme aufgeführt, da es bisher
noch keine ODMG-zertifizierten Systeme gibt.
Darüber hinaus existieren auch Sprachanbindungen an andere Sprachen, wie
15
z.B. Objective-C, CLOS und XML, die jedoch nicht von der ODMG genormt
wurden.
Vor- und Nachteile objektorientierter Datenbanken
Objektorientierte Datenbanken sind besonders gut für die Speicherung komplexer Datenstrukturen geeignet. Komplexe Objekt-Geflechte lassen sich
leicht abbilden und effizient nutzen. Der navigierende Zugriff von einem
Objekt auf ein anderes ist deutlich effizienter realisiert als bei anderen
Datenbank-Technologien.
Die Datenbanken sind eng mit den objektorientierten Programmiersprachen
integriert, wodurch sie einfach zu nutzen sind. Die Abbildung von Objekten
der Programmiersprache in die Datenbank ist vollständig automatisiert. Es
muss kein zusätzliches Datenbankmodell erstellt werden, sondern die Klassen der Programmiersprache können direkt übernommen werden. Das Laden
und Speichern der Objekte zur Laufzeit der Software funktioniert ebenfalls
automatisch.
Die enge Bindung zwischen den Programmiersprachen und den Datenbanken hat jedoch nicht nur Vorteile. Die objektorientierte Datenbanken sind
häufig stark mit dem Programmcode verwoben, z.B. dadurch, dass beim Erzeugen eines Objekts festgelegt wird, ob dieses persistent in der Datenbank
gespeichert werden soll.
Diese Vermischung von datenbankspezifischen Elementen und dem restlichen Programmcode widerspricht der etablierten 3-Schichten-Architektur.
Eine spätere Umstellung auf eine andere Speicher-Technologie bereitet daher
Schwierigkeiten.
Ebenfalls Schwierigkeiten bereitet die Kompatibilität zwischen Datenbanken
unterschiedlicher Hersteller. Obwohl die ODMG seit über 10 Jahren existiert,
ist die ODMG-Spezifikation bisher nur zum Teil erfolgreich umgesetzt. Viele
objektorientierte Datenbanken werden weiterhin auf proprietäre Weise angesprochen, was zum Teil historische Gründe hat. Auch werden teilweise
zusätzliche oder abweichende Funktionen angeboten. So unterstützen manche Datenbanken eine Mehrfachvererbung bei den Klassen. Manche Datenbanken erzeugen Objekte durch gewöhnliche Konstruktoraufrufe und nicht
über Factory-Methoden. Ob ein Objekt persistent oder transient ist, kann
durch einen Methodenaufruf zur Laufzeit festgelegt werden und kann auch
nachträglich wieder geändert werden. Durch diese Abweichungen und datenbankspezifischen Funktionen bindet man sich an einen bestimmten Hersteller,
sobald man die Datenbank verwendet.
16
Objektorientierte Datenbanken sind zudem häufig an eine bestimmte Programmiersprache gekoppelt, so dass nicht immer ohne Probleme von verschiedenen Programmiersprachen aus auf die gleichen Daten zugegriffen werden
kann. Insbesondere für ältere Programmiersprachen, wie z.B. COBOL, ist der
Zugriff auf die Daten nur über Umwege möglich. Manche objektorientierte
Datenbanken erlauben hierfür beispielsweise den Zugriff über SQL-Befehle.
Die objektorientierten Datenbanken haben inzwischen zwar einen ähnlichen
Reifegrad erreicht, wie die relationalen Datenbanken, werden jedoch weiterhin als relativ exotisch angesehen. Dies liegt auch daran, dass die meisten
objektorientierten Datenbanken von kleinen Herstellern angeboten werden.
Die Kunden haben jedoch häufig größeres Vertrauen in die sehr großen und
etablierten Hersteller relationaler Datenbanken.
Auch die gesamte Infrastruktur ist bei den relationalen Datenbanken wesentlich besser ausgebaut. Das Know-How über objektorientierte Datenbanken
ist längst nicht so weit verbreitet, wie es bei relationalen Datenbanken der
Fall ist. Es gibt weit mehr Zusatz-Werkzeuge für die Arbeit mit relationalen
Datenbanken.
Auch aus politischen Gründen werden in vielen Projekten objektorientierte
Datenbanken ausgeschlossen. Beispielsweise werden in sehr vielen Firmen
bereits relationale Datenbanken eingesetzt. Neue Anwendungen müssen die
darin enthaltenen Daten weiter nutzen. Der Administrationsaufwand für eine
weitere Datenbank wäre zu groß.
2.2.3
Enterprise Java Beans
Die von Sun Microsystems spezifizierte Java Technologie Enterprise Java
”
Beans“ (EJB) beschreibt eine Infrastruktur für die Erstellung großer, verteilter Softwareanwendungen. Dabei wird von einer 3-Schichten Architektur
ausgegangen (siehe Abbildung 2.3 auf der nächsten Seite).
Die EJB 3-Schichten-Architektur ist eine konkrete Umsetzung der 3Schichten-Architektur, wie sie in Kapitel 2.1 auf Seite 5 beschrieben wurde.
Die mittlere Schicht, der Applikations-Server, ist dabei der wichtigste Teil
der EJB-Architektur. Auf ihr läuft der EJB-Server, auf dem die EJBs ausgeführt werden. Ein EJB ist eine abgeschlossene Einheit, die einen Teil der
Geschäftslogik der Anwendung kapselt: auch Geschäftsobjekt oder BusinessObject genannt. Dabei werden drei Sorten von EJBs unterschieden: Session
Beans, Entity Beans und Message Beans. Session Beans werden vor allem
dafür eingesetzt, Logik auf dem Server ablaufen zu lassen. Der Zustand des
17
1. Schicht
Client-Anwendung
(Präsentation)
?
2. Schicht
Applikations-Server
(Geschäftslogik)
?
3. Schicht
Datenbank-Server
(Datenhaltung)
Abbildung 2.3: EJB 3-Schichten Architektur
Session Beans wird normalerweise nicht persistent gespeichert, überdauert jedoch die gesamte Kommunikation mit der Client-Anwendung. Message Beans
verhalten sich ähnlich wie Session Beans, werden jedoch durch asynchrone
Nachrichten aufgerufen, die mittels des Java Message Service (JMS) verschickt werden. Entity Beans hingegen beschreiben Objekte der Geschäftslogik, die persistent gespeichert werden.
Jedes EJB hat zwei Interfaces, über die auf das EJB zugegriffen werden
kann: das Home Interface und das Component Interface. Das Home Interface
stellt Methoden für die Verwaltung der EJBs zur Verfügung, z.B. um EJBs
zu erzeugen, aufzufinden und wieder zu löschen. Das Component Interface
enthält alle objektspezifischen Methoden, in denen die Geschäftslogik des
Objekts umgesetzt wird.
Jedes EJB kann wahlweise von einer entfernten Client-Anwendung oder lokal,
z.B. durch andere EJBs, aufgerufen werden. Lokale- und entfernte Aufrufe
werden jedoch über unterschiedliche Interfaces abgewickelt. Beim Home Interface werden das Remote- und Local Home Interface unterschieden. Beim
Component Interface spricht man einfach vom Remote- bzw. Local Interface.
Um ein EJB entfernt aufrufen zu können, muss es ein Remote Home Interface und ein Remote (Component) Interface zur Verfügung stellen. Damit es
lokal aufgerufen werden kann, muss entsprechend ein Local Home Interface
und ein Local (Component) Interface angeboten werden. Um ein EJB über
ein Local Interface aufrufen zu können, muss das aufrufende Objekt zudem in
derselben Java Virtual Machine ausgeführt werden wie das aufgerufene EJB.
Die Client-Anwendung kommuniziert meistens mittels der Remote Interfaces
mit EJBs auf dem EJB-Server.
Der EJB-Server stellt so genannte EJB-Container zur Verfügung. Die EJBs
laufen immer innerhalb eines EJB-Containers ab. Alle Aufrufe an ein EJB
werden über den EJB-Container vermittelt. So kann der EJB-Container vor
und nach dem Aufruf einer Methode eines EJBs aktiv werden. Dadurch kann
er zusätzliche Dienste zur Verfügung stellen. Über dieses Konzept werden
18
beispielsweise Transaktionen angeboten und auch die Persistenz von Entity
Beans kann auf diesem Wege vom EJB-Container verwaltet werden.
Zum Speichern der Entity Beans werden bei den meisten EJB-Servern relationale Datenbanken eingesetzt. Bei der Persistenz von Entity Beans unterscheidet man zwischen Container Managed Persistence“ und Bean Mana”
”
ged Persistence“. Bei Container Managed Persistence“ wird die Speicherung
”
der Daten automatisch vom Container abgewickelt. Bei Bean Managed Per”
sistence“ wird die Speicherung hingegen vom Bean selbst durchgeführt und
muss von Hand programmiert werden. Dadurch ist es jedoch möglich, gezielt
auf die Art der Speicherung Einfluss zu nehmen.
Die gleiche Unterscheidung existiert bei Transaktionen. Auch hier kann man
die Transaktionen automatisch vom Container ausführen lassen, oder aber
selbst steuern, wofür das Java Transaction API zur Verfügung steht. Bei Entity Beans können Transaktionen jedoch nur vom Container gesteuert werden;
ein manueller Eingriff ist hier nicht möglich.
Der Aufbau eines Entity Beans wird in einem so genannten abstract persi”
stence schema“ definiert. Darin werden die folgenden drei Elemente festgehalten:
• Name des Schemas.
• Felder, die persistent gespeichert werden sollen.
• Beziehungen zu anderen Entity Beans.
Jedes Entity Bean erhält zudem eine Objektidentität, über die es lokalisiert werden kann. Darüber hinaus kann jedes Entity Bean in seinem Home
Interface weitere Methoden anbieten, um Objekte zu suchen: die so genannten Finder-Methoden. Um auf die gespeicherten Daten zuzugreifen, wird die
EJB Query Language (EJB QL) angeboten, die auf der Select-Anweisung von
SQL-92 aufbaut. Für jede Finder-Methode wird eine EJB QL Query spezifiziert. Eine EJB QL Query bezieht sich immer auf das abstract persistence
”
schema“ und nicht auf die zugrunde liegende physikalische Struktur der Datenbank, so dass in der Select-Anweisung abstrakte Schemata anstelle von
Tabellen benannt werden. Zudem ist es möglich, die im Schema spezifizierten
Referenzen in einer Anfrage zu verfolgen.
Die EJB QL ähnelt damit den Erweiterungen die in SQL:1999 eingeführt
wurden. Die Möglichkeiten der Datenmodellierung sind in etwa vergleichbar.
Bei den EJBs ist das Erstellen und Verwalten der Referenzen jedoch einfacher: Es müssen keine Objektidentitäten explizit erzeugt und gehandhabt
19
werden. Das Verknüpfen von Referenzen funktioniert bei den EJBs ähnlich
einfach wie das Verknüpfen einer normalen Java Objektreferenz.
Vor- und Nachteile der EJB-Architektur
Die Architektur entspricht weitestgehend der etablierten 3-SchichtenArchitektur. Wichtige Aufgaben, wie Persistenz und Transaktionen, werden
durch die Architektur unterstützt und erleichtert. Dadurch wird die gemeinsame Nutzung der Objekte durch mehrere Clients wesentlich erleichtert.
Andererseits ergibt sich dadurch ein starker Einfluss auf den SoftwareEntwurf. Es ist festgelegt, dass die Beans auf einem Applikationsserver ablaufen. Dadurch wird eine Aufteilung der Software in einen Client- und einen
Server-Teil erzwungen. Zugriffe finden über das Netzwerk statt. Wenn die
Anwendung eine hohe Interaktion mit den Komponenten auf dem Server
hat, wirkt sich diese Trennung negativ auf die Gesamtleistung aus. Dies ist
auch der Grund, warum EJB keine geeignete Speicher-Technologie für eine
WAM-Anwendung darstellt. Die Interaktion mit den zu bearbeiteten Materialien ist meist sehr hoch und die ständigen Netzwerkzugriffe verlangsamen
die Anwendung erheblich.
Nicht alle Entity Beans können automatisch persistent verwaltet werden.
Komplexere Strukturen müssen von Hand in einer relationalen Datenbank
abgelegt werden. Die automatische Persistenz-Verwaltung fällt damit weg.
Dies ist auch dann der Fall, wenn bereits Daten in einer Datenbank gespeichert sind. Die EJB-Architektur liefert keine Hilfestellung beim Umgang mit
bereits bestehenden Datenbanken.
EJB ist eine Java-spezifische Technologie. Die Koordination mit anderen Programmiersprachen ist in der Spezifikation nicht berücksichtigt. Daher ist es
nicht ohne weiteres möglich, mit anderen Programmiersprachen auf die gespeicherten Daten zuzugreifen.
2.3
Auswertung
Die aufgeführten alternativen Technologien haben jeweils spezifische Vorund Nachteile, die einen Einsatz abhängig von den Anforderungen unterstützen oder verhindern können.
Die relationalen Datenbanken habe sich zwar etabliert, es bestehen jedoch
wesentliche Nachteile, auf die im nächsten Kapitel noch genauer eingegangen
wird. Auch Mapping-Tools können die Probleme nur bedingt beheben.
20
Die objektorientierten Datenbanken stellen eine brauchbare Alternative für
viele objektorientierte Softwareanwendungen dar. Ihre gute Integration mit
den Programmiersprachen verringern den Entwicklungsaufwand erheblich.
Herstellerübergreifende Standards sind jedoch bisher unzureichend umgesetzt, so dass meist eine Abhängigkeit zu einem bestimmten Produkt entsteht. Häufig verhindert jedoch ein mangelndes Vertrauen in die Produkte
oder die Hersteller den Einsatz. Ob dies gerechtfertigt ist, kann im Rahmen
dieser Arbeit nicht geklärt werden.
Die EJB-Architektur stellt für die hochgradig interaktiven JWAMAnwendungen keine brauchbare Alternative zur Verfügung. Die zentrale Objektverwaltung auf einem Server im Zusammenhang mit der hohen Interaktion zwischen Werkzeug und Material führt dazu, dass sehr viele Zugriffe über
das Netzwerk durchgeführt werden müssen. Dies verlangsamt die Software
jedoch beträchtlich.
21
22
Kapitel 3
Konzeption
Als zentrale Frage der Arbeit soll die Integration objektorientierter Konzepte in das relationale Modell diskutiert werden. In diesem Kapitel werden
das objektorientierte Modell und das relationale Modell jeweils für sich kurz
vorgestellt. Dabei werden die wichtigsten Elemente der jeweiligen Modelle beschrieben. Anschließend werden die Modelle miteinander verglichen, um die
bestehenden Diskrepanzen hervorzuheben. Danach werden mögliche Erweiterungen beschrieben, die eine besser Kombination der Modelle ermöglichen
würden. Im Anschluß wird das objektrelationale Modell, als eine konkrete
Erweiterung des relationalen Modells, präsentiert und bewertet.
3.1
Objektorientiertes Modell
Bisher gibt es kein allgemein anerkanntes, formales objektorientiertes Modell,
das in objektorientierten Systemen, Datenbanken ebenso wie Programmiersprachen, umgesetzt wird. Daraus ergibt sich, dass die Konzepte in den verschiedenen Systemen im Detail unterschiedlich umgesetzt werden. Bezüglich
der meisten Konzepte besteht jedoch ein gemeinsames Grundverständnis
(vgl. [Züllighoven et al. 98]). Im Folgenden sollen diese Konzepte kurz dargestellt werden. Dabei wird herausgearbeitet, wie die Konzepte hier verstanden werden. Das hier verwendete objektorientierte Modell orientiert sich an
den objektorientierten Programmiersprachen, zumal im Folgenden beurteilt
werden soll, wie objektorientierte Programmiersprachen mit relationalen Datenbanken besser integriert werden können.
Das entscheidende Element der Objektorientierung ist die Erweiterbarkeit des Typsystems. Zusätzlich zu den bestehenden Standard-Datentypen
können neue Datentypen definiert werden. Datentypen werden im objektorientierten Modell vor allem durch ihr Verhalten beschrieben. Es handelt sich
23
also um eine verhaltensorientierte Modellierung. Bertrand Meyer beschreibt
einen Typ wie folgt: a type is a collection of objects characterized by functi”
ons, axioms and preconditions“ (vgl. [Meyer 97], S. 130). Typen werden also
ausschließlich dadurch charakterisiert, welche Funktionen auf den Objekten
ausgeführt werden können, welche Axiome erfüllt sind und welche Vorbedingungen im Umgang mit den Funktionen eingehalten werden müssen. Wie die
Objekte ihren internen Zustand repräsentieren und wie sie strukturiert sind,
ist für die Beschreibung des Typs unerheblich.
In den meisten objektorientierten Programmiersprachen gibt es eine 1:1Bindung zwischen Klassen und Datentypen. Eine neue Klasse definiert automatisch auch einen neuen Datentyp im Typsystem. Meyer definiert eine
Klasse wie folgt: A class is an abstract data type equipped with a possibly
”
partial implementation.“ (vgl. [Meyer 97], S. 142). Eine Klasse ist also eine
konkrete Implementation eines Datentyps. In einer Klasse werden die Daten mit den dazugehörigen Methoden zusammengefasst. Die Daten werden
in Instanzvariablen gespeichert. Der Zugriff auf die gekapselten Daten findet
über die Methoden statt. Die Methoden der Klasse definieren die möglichen
Funktionen des neuen Datentyps. Die Methoden stellen ebenfalls sicher, dass
das Objekt nicht in einen inkonsistenten Zustand gerät.
Eine Besonderheit der Objektorientierung ist die Vererbung. Ein Subtyp erbt
die Eigenschaften des Supertyps und kann diese erweitern und verändern.
Objekte eines Subtyps können polymorph überall dort eingesetzt werden,
wo Objekte des Supertyps möglich sind. Dies wird auch als Substitution
bezeichnet. Beim Aufruf einer Methode wird zur Laufzeit dynamisch die entsprechende Methode des Subtyps ausgeführt, was als Polymorphie bezeichnet
wird.
Zur Laufzeit des Systems werden Objekte frei im Speicher erzeugt. Sie sind
immer Exemplare genau einer erzeugenden Klasse. Da in den gängigen Programmiersprachen jede Klasse mit genau einem Typ assoziiert ist, hat damit
jedes Objekt genau einen Typ, der über die gesamte Lebenszeit des Objekts
erhalten bleibt. Objekte können also zur Laufzeit ihre Typ- oder Klassenzugehörigkeit nicht verändern.
Zudem bekommt ein Objekt bei seiner Erzeugung eine eigene Identität, die
es ebenfalls bis zu seiner Vernichtung beibehält. Diese Objektidentität ist
unabhängig vom internen Zustand des Objekts. Über die Objektidentität
können Objekte auch eindeutig referenziert werden. So können Variablen auf
Objekte verweisen, indem die Objektidentität in der Variablen gespeichert
wird. Objekte werden durch Referenzen miteinander verknüpft, indem die
Objektidentität eines Objekts in einer Instanzvariablen eines anderen Ob24
jekts gespeichert wird. Auf Objekte wird über Referenzen zugegriffen. Dabei
werden die Methoden eines Objekts aufgerufen.
In Tabelle 3.1 sind die Eigenschaften des objektorientierten Modells noch
einmal zusammengefasst dargestellt.
objektorientiertes
Modell
verhaltensorientierte
Modellierung
imperatives
Paradigma
erweiterbares
Typsystem
Vererbung
Polymorphie
Objekte mit
unveränderlichem Typ
Objektidentität
unabhängig
von Werten
Verknüpfung durch
Referenzen
Objekte
frei im Speicher
Zugriff durch
Methodenaufrufe
Verarbeitung
einzelner Objekte
Zustand
der Objekte
gekapselt
Methoden an
Objekte gebunden
Tabelle 3.1: Eigenschaften des objektorientierten Modells
25
3.2
Relationales Modell
Die Relationalen Datenbanken basieren auf dem Relationenmodell, das erstmals von Codd beschrieben wurde (vgl. [Codd 70]).
Das Relationenmodell setzt sich aus einem Strukturteil und einem Operationenteil zusammen. Der Strukturteil beschreibt die Aspekte des Modells,
mit denen man definieren kann, in welchen Strukturen die Daten abgelegt
werden sollen. Dabei legt man fest, welche Daten gespeichert werden sollen,
und wie diese gruppiert und untereinander verknüpft werden. Der Operationenteil hingegen beschreibt, welche Operationen man auf die gespeicherten
Daten anwenden kann.
Der Grundgedanke des relationalen Modells besteht darin, eine Faktenbasis
zur Verfügung zu stellen, aus der Aussagen abgeleitet werden können. ... the
”
model is based on first-order predicate logic.“ (vgl. [Codd 90], S. 459). Im
Strukturteil wird festgelegt, wie der Aufbau einer Faktenbasis beschrieben
wird. Der Operationenteil beschreibt eine feste Menge von Operationen, mit
deren Hilfe die Aussagen abgeleitet werden können: It has been proved that,
”
collectively, these operators have the same expressive power as first-order
predicate logic.“ (vgl. [Codd 90], S. 61).
Der Strukturteil des Relationenmodells ist getypt. Um Daten speichern zu
können, müssen Attribute definiert werden, denen jeweils genau ein Datentyp zugewiesen wird, was auch den möglichen Wertebereich des Attributs
einschränkt. Dies wird auch als Domäne (domain) des Attributs bezeichnet.
Im Strukturteil ist nicht festgelegt, welche Datentypen es gibt, so dass dies
der konkreten Implementation überlassen bleibt. Gängige Datentypen sind
z.B. ganze Zahlen und Texte. So könnte man beispielsweise das Attribut
Name“ mit dem Wertebereich Text“ definieren und von nun an beliebi”
”
ge Namen als Text in diesem Attribut speichern. Attribute werden jedoch
nicht als einzelne Einheiten definiert, sondern immer in n-stellige Relationen
gruppiert, wodurch mehrere Attribute in Relation zueinander gesetzt werden.
Die Beschreibung einer Relation, also welche Attribute mit welchen Datentypen Teil der Relation sein sollen, bezeichnet man als Relationenschema.
Eine konkrete Relation ist nun eine Teilmenge des kartesischen Produkts aller Wertebereiche, die im Relationenschema definiert wurden. Ein einzelnes
Element einer Relation wird als Tupel bezeichnet.
Die Relationen werden bei den Datenbanken anschaulich als Tabellen dargestellt. Dabei nimmt jede Spalte ein Attribut auf. Jede Zeile enthält ein Tupel
der Relation. Eine Relation ist eine konkrete Füllung der Tabelle mit Daten
26
Name
Monika Schmidt
Peter Petersen
Maria Müller
Justus Eichborn
Straße
Rübenstraße 103
Borgweg 23
Waldweg 12b
Beim Stoppel 3
Postleitzahl
63232
23456
33455
12231
Ort
Freiburg
Hamburg
Bremen
Berlin
Abbildung 3.1: Eine Relation mit vier Attributen in Tabellenform dargestellt.
(siehe Abbildung 3.1). Im Folgenden werden die beiden Begriffe synonym
verwendet.
Die Attribute einer Relation können nur atomare Werte aufnehmen. So ist
es beispielsweise nicht möglich, in einem Attribut eine Liste von Zahlen zu
erfassen, sondern immer nur eine einzelne Zahl. Ein Attribut selbst kann
auch keine geschachtelten Attribute enthalten. Es ist somit nicht möglich,
strukturierte Attributwerte oder geschachtelte Tabellen zu definieren. Diese
Einschränkung wird als erste Normalform für Relationen bezeichnet. Häufig
nennt man Relationen, die der ersten Normalform gehorchen, auch flache
Relationen.
Eine weiteres Element des Strukturteils sind die so genannten Schlüssel. Um
sicher zu gehen, dass alle Tupel einer Relation unterscheidbar sind, wird eine
identifizierende Attributmenge festlegen. Eine identifizierende Attributmenge zeichnet sich dadurch aus, dass keine zwei Tupel in allen in ihr enthaltenen
Attributen übereinstimmen. Man kann somit jedes Tupel eindeutig bestimmen, wenn man Werte für alle Attribute der identifizierenden Attributmenge
angibt. Wenn die identifizierende Attributmenge zudem bezüglich der Teilmengenrelation minimal ist, es also keine kleinere Teilmenge von Attributen
gibt, die ebenfalls identifizierend ist, wird diese als Schlüssel bezeichnet.
Ein im Datenbankentwurf ausgewiesener Schlüssel wird als Primärschlüssel
bezeichnet. Primärschlüssel werden zum einen zur Absicherung der Datenkonsistenz eingesetzt, damit keine zwei Tupel in einer Relation vorkommen
können, die in allen Attributen des Schlüssels übereinstimmen. Zum anderen
werden sie eingesetzt, um Verweise zwischen den Tupeln unterschiedlicher
Relationen herzustellen. Daten im Relationenmodell werden ausschließlich
über die gespeicherten Werte der Attribute identifiziert.
Um eine Beziehung zwischen zwei Relationen herzustellen, werden die gleichen Attribute, die den Primärschlüssel einer Relation ausmachen, auch in
einer zweiten Relation definiert. Dort bezeichnet man diese Attributmenge
als Fremdschlüssel. Bei jedem Tupel der zweiten Relation können in den Attributen, die zum Fremdschlüssel gehören, die Werte des Primärschlüssels
27
Primärschlüssel
Name
Geb.-Datum
Monika Schmidt 20.08.1954
Peter Petersen
01.12.1972
Maria Müller
14.03.1966
Justus Eichborn 11.11.1971
Rechnungsnummer
366-6223-342
223-4443-112
321-1234-552
554-2233-562
Straße
Rübenstraße 103
Borgweg 23
Waldweg 12b
Beim Stoppel 3
...
...
...
...
...
Fremdschlüssel
Kundenname
Kunden Geb.-Datum
Monika Schmidt 20.08.1954
Peter Petersen
01.12.1972
Monika Schmidt 20.08.1954
Maria Müller
14.03.1966
Abbildung 3.2: Fremdschlüsselbeziehung zwischen zwei Relationen
eines Tupels der ersten Relation gespeichert werden. Anhand der im Fremdschlüssel des Tupels der zweiten Relation gespeicherten Werte kann das zugehörige Tupel in der ersten Relation ausfindig gemacht werden (siehe Abbildung 3.2).
Zusätzlich können im relationalen Modell Konsistenzbedingungen ( Cons”
traints“) definiert werden. Damit ist eine Sicherung der Datenkonsistenz
möglich, so dass ein Zugriff, der zu einem inkonsistenten Zustand führen
würde, erkannt und abgefangen werden kann.
Im Operationenteil des Relationenmodells sind generische Operationen festgelegt, mit deren Hilfe auf die in den Relationen gespeicherten Daten zugegriffen werden kann. Es stehen die folgenden Operationen zur Verfügung:
Selektion zur Auswahl bestimmter Tupel (Zeilen) einer Relation
Projektion zur Auswahl bestimmter Attribute (Spalten) einer Relation
natürlicher Verbund (auch Join genannt) zum Verbinden mehrerer Relationen anhand von gemeinsamen Attributen (vor allem bei Fremdschlüsselbeziehungen)
Umbenennung zum Ändern von Attributbezeichnungen, um Kollisionen
beim natürlichen Verbund aufzulösen
Mengenoperationen Vereinigung, Durchschnitt und Differenz können auf
Relationen mit gleichem Relationenschema angewendet werden
Alle Operationen liefern als Ergebnis wiederum Relationen und können da28
durch beliebig orthogonal miteinander kombiniert werden. Diese Eigenschaft
wird auch als Abgeschlossenheit bezeichnet.
3.2.1
Vor- und Nachteile des relationalen Modells
Das Relationenmodell hat einige Eigenschaften, die für die Anwendung in
Datenbanken von besonderem Vorteil sind. Die im Operationenteil des Relationenmodells zur Verfügung gestellten Operationen sind effizient realisierbar
und maximal von quadratischer Komplexität zur Anzahl der bearbeiteten
Tupel. Aufgrund der Abgeschlossenheit des Modells lassen sich alle Operationen orthogonal miteinander kombinieren. Diese Eigenschaft erleichtert es
außerdem, Anfragen zu optimieren, da sich Teilausdrücke einer Anfrage durch
andere ersetzen lassen, die ein äquivalentes Ergebnis in kürzerer Zeit liefern.
Zudem ist das Modell sicher, was bedeutet, dass eine syntaktisch korrekte
Anfrage immer in endlicher Zeit ein endliches Ergebnis liefert. Ferner lässt
sich zeigen, dass die zur Verfügung gestellten Operationen alle Konzepte des
zugrunde liegenden Datenmodells ausnutzen, was als Adäquatheit bezeichnet
wird. Darüber hinaus erlaubt das Modell den zeitgleichen parallelen Zugriff
sowie eine verteilte Datenhaltung (vgl. [Codd 90]).
Aufgrund der oben aufgeführten Eigenschaften ist es möglich, auf der Basis des Relationenmodells leistungsfähige Datenbanken zu entwickeln, die
auch sehr große Datenmengen verwalten können. Dabei sind selbst komplexe Suchanfragen relativ effizient realisierbar. Beispiele für solche Datenbanken sind unter anderem: IBM DB2, Oracle, Microsoft SQLServer und
Sybase Adaptive Server. Diese Datenbanken haben inzwischen eine hohe Leistungsfähigkeit erreicht. Sie skalieren auf viele tausend Anfragen pro Sekunde
und erlauben den zeitgleichen parallelen Zugriff vieler Anwendungen, ohne
die Konsistenz der gespeicherten Daten zu gefährden (vgl. [TPC]). Ihre hohe
Zuverlässigkeit und Robustheit macht sich in kurzen Ausfallzeiten bemerkbar. Ausgefeilte Sicherheitskonzepte sorgen dafür, dass nur ausgewählte Benutzer Zugriff auf die (möglicherweise sehr sensiblen) Daten erhalten. Die
standardisierte Abfragesprache SQL ermöglicht es, auf die Datenbanken zuzugreifen. Da SQL standardisiert ist und von allen Datenbanken gleichermaßen unterstützt wird, ist eine Austauschbarkeit der konkreten Datenbankimplementation durch die eines anderen Herstellers relativ einfach möglich. In
der Praxis ergeben sich hier jedoch immer wieder Probleme, da nicht alle
Datenbanken den SQL-Standard auf identische Weise umsetzen.
Für viele Programmiersprachen stehen zudem Bibliotheken bereit, die einen
Zugriff auf relationale Datenbanken mittels SQL ermöglichen. Dadurch ist
es problemlos möglich, gemeinsam von verschiedensten Anwendungen aus
29
auf eine gemeinsame Datenbasis zuzugreifen. Und nicht zuletzt aufgrund der
großen Verbreitung relationaler Datenbanken gibt es viel Erfahrung im Umgang mit SQL und relationalen Datenbanken seitens der Softwareentwickler
und Datenbankadministratoren.
Es ist zu beachten, dass bei den konkreten Implementierungen des Relationenmodells meist nicht alle Eigenschaften gewahrt bleiben. Andererseits werden zusätzliche Eigenschaften hinzugefügt. Längst nicht alle Einschränkungen einer konkreten Implementierung sind auf mangelnde Eigenschaften des
Relationenmodells zurückzuführen. So erfüllt die Anfragesprache SQL, die
von den meisten relationalen Datenbanken unterstützt wird, nicht alle Anforderungen des Relationenmodells. Beispielsweise ist SQL nicht abgeschlossen. Deswegen ist es nicht möglich, alle Operationen beliebig miteinander zu
kombinieren, wie dies im Relationenmodell möglich ist.
3.3
Diskrepanzen zwischen den Modellen
Das relationale Modell unterscheidet sich in vielerlei Hinsicht vom objektorientierten Modell (vgl. Tabelle 3.2 auf Seite 33). Der gemeinsame Einsatz
von relationalen Datenbanken und objektorientierten Programmiersprachen
wird dadurch erschwert. Im Folgenden sollen die bestehenden Diskrepanzen noch einmal explizit herausgestellt werden. Dabei wird herausgearbeitet
werden, welche Änderungen und Ergänzungen in den bestehenden Modellen
nötig wären, um die Modelle besser miteinander zu verbinden und somit den
gemeinsamen Einsatz zu erleichtern.
Die Verarbeitung von Daten innerhalb einer Programmiersprache und die
Speicherung von Daten in einer Datenbank stellen grundlegend unterschiedliche Anforderungen. Daher unterliegen die objektorientierten Programmiersprachen einem anderen Paradigma als die relationalen Datenbanken. Wie
Scott Ambler schreibt (vgl. [Ambler 00]):
The object paradigm is based on software engineering principles
such as coupling, cohesion, and encapsulation, whereas the relational paradigm is based on mathematical principles, particularly
those of set theory. The two different theoretical foundations lead
to different strengths and weaknesses. Furthermore, the object
paradigm is focused on building applications out of objects that
have both data and behavior, whereas the relational paradigm is
focused on storing data.
30
Der grundlegende Unterschied besteht darin, dass im objektorientierten Modell Objekte miteinander kooperieren, um ein gewünschtes Verhalten zu erbringen. Im relationalen Modell hingegen werden Informationen gespeichert,
die abgefragt und verändert werden können.
Das objektorientierte Modell ist vornehmlich zur Erstellung von Software
entwickelt worden. Daher konzentriert es sich auf die Modellierung des Verhaltens einer Softwareanwendung.
Das relationale Modell ist hingegen speziell für die Verarbeitung großer Datenmengen konzipiert worden. Es konzentriert sich entsprechend auf die Modellierung von Datenstrukturen, die gespeichert, angefragt und verändert
werden sollen. Verhalten, wie es in der Software durch Algorithmen ausgedrückt wird, spielt dabei keine Rolle.
Das objektorientierte Modell basiert auf einem imperativen Programmiermodell. Die Operationen des Relationenmodells sind jedoch deskriptiv.
Im objektorientierten Modell besitzt jedes Objekt eine unveränderliche Identität, die unabhängig vom Zustand des Objekts ist. Die Identität wird verwendet, um Objekte durch Referenzen miteinander zu verknüpfen.
Im Relationenmodell ist ein einzelner Datensatz nur über die gespeicherten
Werte identifizierbar. Für die Verknüpfung von Datensätzen werden Fremdschlüsselbeziehungen verwendet, die ausschließlich auf dem Vergleich von den
gespeicherten Werten der Datensätze basieren.
Ein weiterer Unterschied besteht beim Typsystem. Im objektorientierten Modell ist das erweiterbare Typsystem ein wichtiger Teil des Modells. Zudem
können neue Typen durch Vererbung gebildet werden. Zur Laufzeit kann
polymorph auf Objekte zugegriffen werden, die in einer Subtyp-Beziehung
zueinander stehen.
Das relationale Modell macht keine Aussage über Datentypen, außer dass
Attribute einen Datentyp zugewiesen bekommen. Welche Datentypen es gibt,
und wie diese geformt werden, ist nicht Teil des Modells. Das relationale
Modell trifft somit auch keine Aussage bezüglich Vererbung.
Die bestehenden relationalen Datenbanken haben gewöhnlich ein abgeschlossenes Typsystem. Sie besitzen einen festen Satz von Standard-Datentypen,
der sich nicht einfach erweitern lässt. Vererbung wird nicht unterstützt.
Im relationalen Modell werden alle Daten in Tabellen strukturiert. Zur Bearbeitung der Tabellen wird eine feste Menge generischer Operationen zur
Verfügung gestellt, die nicht an bestimmte Datentypen gebunden sind. Da
31
die Operationen ausschließlich auf den relationalen Strukturen arbeiten, ist
der Inhalt der Attribute unerheblich. Die in den Attributen gespeicherten
Daten können direkt zugegriffen und manipuliert werden. Zudem wirken sich
die Operationen des Modells immer auf gesamte Tabellen aus und nicht auf
einzelne Datensätze. Mittels Selektion und Projektion kann jedoch ein Teil
einer Tabelle ausgewählt werden.
Das objektorientierte Modell legt hingegen keine Struktur fest, in der Objekte
abgelegt werden. Diese existieren frei im Speicher und sind durch Referenzen
miteinander verknüpft. Die Manipulation von Objekten ist nur durch Methodenaufrufe an den Objekten möglich, wobei die Objekte einzeln verarbeitet
werden. Der innere Zustand der Objekte ist gekapselt und damit nicht direkt zugreifbar. Es gibt keine generischen Operationen, die auf einer Menge
beliebiger Objekte ausgeführt werden können.
Im relationalen Modell können Konsistenzbedingungen definiert werden, die
einen inkonsistenten Zustand der Daten verhindern. Im objektorientierten
Modell werden solche Bedingungen in den Axiomen eines abstrakten Datentyps festgehalten.
In den bestehenden Programmiersprachen gibt es selten Mechanismen zur
Definition von Axiomen und somit zur Absicherung der Konsistenz. Die Konsistenz wird implizit dadurch gesichert, dass ausschließlich Methoden den Zustand der Objekte verändern. Es wird davon ausgegangen, dass die Methoden
so erstellt wurden, dass sie keinen inkonsistenten Zustand herstellen.
Die wichtigsten Eigenschaften des objektorientierten Modells im Vergleich
zum relationalen Modell sind noch einmal in Tabelle 3.2 auf der nächsten
Seite gegenübergestellt.
Nachdem die konzeptionellen Unterschiede dargestellt wurden, stellt sich die
Frage, wie diese Unterschiede überbrückt werden können. Um eine optimale
Integration der beiden Modelle zu erreichen, sind Anpassungen in beiden
Modellen denkbar. In den folgenden zwei Abschnitten werden für die beiden
Modelle die jeweils nötigen Anpassungen dargestellt.
32
objektorientiertes
Modell
verhaltensorientierte
Modellierung
imperatives
Paradigma
erweiterbares
Typsystem
Vererbung
Polymorphie
Objekte mit
unveränderlichem Typ
Objektidentität
unabhängig
von Werten
Verknüpfung durch
Referenzen
Objekte
frei im Speicher
Zugriff durch
Methodenaufrufe
Verarbeitung
einzelner Objekte
Zustand
der Objekte
gekapselt
Methoden an
Objekte gebunden
Konsistenzsicherung
durch Axiome
und Methoden
relationales
Modell
strukturorientierte
Modellierung
ohne Verhalten
deskriptives
Paradigma
Typsystem außerhalb
des Modells
keine Vererbung
keine Polymorphie
keine Objekte
keine Identität
unabhängig
von Werten
Verknüpfungen durch
Fremdschlüssel
Daten
in Tabellen
strukturiert
Zugriff durch
rel. Algebra
Verarbeitung
mehrerer Datensätze
Zustand
der Daten
frei zugreifbar
keine Methoden
Konsistenzsicherung
durch Constraints
Tabelle 3.2: Relationales Modell im Vergleich zum OO-Modell
33
3.3.1
Anpassungen am relationalen Modell
Wie im vorangegangenen Kapitel erläutert, unterstützt das relationale Modell einige Konzepte des objektorientierten Modells nicht. Dazu zählen:
• Kein erweiterbares Typsystem mit der Möglichkeit, neue Datentypen
zu erstellen.
• Keine Unterstützung für Vererbung zwischen Datentypen.
• Keine Modellierung von Verhalten, daher auch keine Datenkapselung
durch Methoden.
• Keine von den gespeicherten Werten unabhängige Identität.
Die fehlenden Konzepte sind jedoch größtenteils orthogonal zu den bestehenden Konzepten des relationalen Modells und können daher problemlos in das
Modell integriert werden.
Ein wesentlicher Teil des objektorientierten Modells ist die Erweiterbarkeit
des Typsystems. Das relationale Modell macht hingegen keine Aussagen über
das verwendete Typsystem. Die Aufnahme eines erweiterbaren Typsystems
in das Modell wäre jedoch hilfreich, um komplexe Datentypen verarbeiten
zu können. Dies würde den Austausch komplexer Datentypen zwischen den
Modellen ermöglichen. Die Vererbung sollte bei der Erweiterung des Typsystems ebenfalls anwendbar sein. Attribute einer Tabelle sollten polymorph
auch Objekte eines Subtyps des eigenen Typs aufnehmen können.
Ein weiterer gravierender Unterschied besteht darin, dass im relationalen Modell kein Verhalten modelliert werden kann. Daten sind frei zugreifbar und
werden direkt abgefragt und manipuliert. Die Bildung abstrakter Datentypen, wie im objektorientierten Modell möglich, ist somit ausgeschlossen.
Das relationale Modell sollte die Bildung abstrakter Datentypen unterstützen. Verhalten, in Form von Methoden, sollte an Datentypen gebunden
werden können. Der Zugriff auf Objekte sollte über die Methoden abgewickelt
werden. Dadurch kann ein konsistenter Umgang mit den Objekten sichergestellt werden, wodurch auch ein konsistenter Zustand der Objekte gewahrt
bleibt. Beim Zugriff auf Methoden sollte Polymorphie ebenso unterstützt
werden.
Größere Probleme bereitet die Objektidentität. Im objektorientierten Modell werden Objekte mit einer eigenen Objektidentität versehen, so dass die
Objekte durch Referenzen miteinander verknüpft werden können.
Das relationale Modell unterstützt keine Identität unabhängig von den gespeicherten Werten. Daher gibt es auch keine Referenzen oder Pointer. Alle
34
Beziehungen werden ausschließlich durch Werte-Vergleich hergestellt. Codd
begründet dies wie folgt (vgl. [Codd 90], S. 463):
It is safe to assume that all kinds of users understand the act of
comparing values, but that relatively few understand the complexities of pointers. The relational model is based on this fundamental principle. Note also that the manipulation of pointers is
more bug-prone than is the act of comparing values, even if the
user happens to understand the complexities of pointers.
Eine Einführung von IDs und Referenzen bzw. Pointern würde das Modell
in der Tat deutlich verkomplizieren. Eindeutigkeit lässt sich im relationalen Modell jedoch recht einfach durch so genannte Surrogate herstellen. Ein
Surrogat ist ein Schlüssel-Attribut ohne fachliche Bedeutung. Es dient ausschließlich zur Identifikation des Datensatzes. Dieses Konstrukt verhält sich
ebenso wie eine Objektidentität.
Es ist jedoch nicht ratsam, für jeden Datensatz prinzipiell eine zusätzliche
Spalte mit einem Surrogat vorzusehen. Surrogate bieten sich vor allem dort
an, wo Elemente zwar fachlich unterschieden werden müssen, eine Unterscheidung anhand der gespeicherten Werte jedoch nicht praktikabel oder zu
umständlich ist.
3.3.2
Anpassungen am objektorientierten Modell
Auch im objektorientierten Modell gibt es kaum prinzipielle Probleme, die
eine Integration der Konzepte des relationalen Modells verhindern. Mit der
Möglichkeit, neue Datentypen zu erstellen und in das System zu integrieren,
kann man prinzipiell auch die Konzepte des relationalen Modells weitgehend
integrieren. Mögliche Ansätze einer Integration wurden von Jens Coldewey
und Wolfgang Keller beschrieben (vgl. [Keller, Coldewey 97]).
Dabei ist zu berücksichtigen, dass mit einer Integration hier nicht eine automatische Abbildung der relational strukturierten Daten auf Objekte und
Objekt-Strukturen und umgekehrt gemeint ist. Wenn wir davon ausgehen,
dass in einem erweiterten relationalen Modell komplex strukturierte Objekte
möglich sind, ist ein direkter Austausch von Objekten zwischen den Modellen
möglich. Im Folgenden ist vielmehr der Umgang mit relational strukturierten
Daten innerhalb des objektorientierten Modells gemeint.
Der größte Unterschied zwischen den Modellen ist, dass Objekte im objektorientierten Modell frei im Speicher erzeugt werden, wohingegen im relationalen
Modell die Daten in einer übergeordneten Struktur, den Relationen, abgelegt
35
werden. Erst diese Strukturierung ermöglicht den Zugriff auf die Daten mit
Hilfe der relationalen Algebra.
Es wäre eine gravierende Änderung, wenn man auch im objektorientierten
Modell eine übergeordnete Struktur einführen würde. Diese würde die Flexibilität stark einschränken. Stattdessen könnte ein Datentyp erstellt werden,
der relational strukturierte Daten aufnehmen und verarbeiten kann. Der so
erstellte Datentyp wäre mit Container-Datentypen, wie z.B. einer Liste, vergleichbar. Bei der Erstellung eines Objekts des relationalen Datentyps könnte
die konkrete Struktur der Relation festgelegt werden. Die relationale Algebra
könnte durch Methoden an diesem Datentyp umgesetzt werden.
Dass im relationalen Modell keine Identität existiert, kann dadurch ausgeglichen werden, dass keine Identitätsvergleiche auf Objekte angewendet werden,
die einen relationalen Datentyp besitzen, oder in einem relationalen Objekt
abgelegt sind. Dies kann in den objektorientierten Programmiersprachen auch
konstruktiv unterstützt werden.
3.4
Objektrelationale Datenbanken
In den vorangegangenen Kapiteln wurde dargestellt, welche grundlegenden
Probleme bei der Kombination des objektorientierten Modells mit dem relationalen Modell bestehen. Es wurden einige Anpassungen der Modelle angerissen, die eine bessere Integration schaffen könnten.
Für die vorliegende Arbeit sind besonders die Erweiterungen des relationalen Modells von Interesse. Um den geschilderten Problemen des relationalen
Modells entgegenzuwirken, wurde das relationale Modell um objektorientierte Konzepte zu einem objektrelationalen Modell erweitert. Auf diese Weise
wird versucht, die Vorteile des relationalen Modells mit den Möglichkeiten
der Objektorientierung zu verbinden.
Die im Kapitel 3.3.1 auf Seite 34 aufgeführten Defizite des relationalen Modells sollen im objektrelationalen Modell behoben werden.
Dabei soll sichergestellt werden, dass die Erweiterungen konform zum relationalen Modell durchgeführt werden.
3.4.1
Objektrelationales Modell
Es gibt, ähnlich wie beim objektorientierten Modell, bisher kein allgemein
anerkanntes, formales objektrelationales Modell. Das bisher ausführlichste
36
objektrelationale Modell wurde von C. J. Date und Hugh Darwen ausgearbeitet und ist in ihrem Buch The Third Manifesto“ beschrieben (vgl.
”
[Date, Darwen 00]):
The Third Manifesto is a detailed proposal for the future direction of data and database management systems (DBMSs). Like
Codd’s original papers on the relational mode, it can be seen as
an abstract blueprint for the design of a DBMS and the language
interface to such a DBMS.
Da bisher keine vergleichbare Ausarbeitung existiert, wird dieses Modell auch
hier als Grundlage angenommen.
Das Modell beschreibt, wie objektorientierte Konzepte in das relationale
Modell integriert werden können, ohne die bestehenden Elemente zu beeinträchtigen. Die nötigen Erweiterungen sind vollständig orthogonal zum
relationalen Modell. Die relationalen Strukturen und Eigenschaften bleiben
auch im objektrelationalen Modell weiterhin das bestimmende Element.
Im Folgenden werden die wichtigsten Eigenschaften dieses Modells dargestellt. Anschließend wird es kritisch betrachtet und bestehende Probleme
werden aufgezeigt.
Im relationalen Modell wurde nicht beschrieben, wie Datentypen gebildet
werden. Das relationale Modell selbst macht zwar keine Einschränkungen
bezüglich der möglichen Typen, es wird jedoch keine Aussage darüber getroffen, ob und wie neue Datentypen erzeugt werden können. Im relationalen
Modell wird lediglich festgehalten, dass die Attribute einen Typ zugewiesen
bekommen. Die Attribute können nur Werte dieses Typs aufnehmen.
Die Typkonstruktoren sind daher eine wichtige Erweiterung des objektrelationalen Modells. Sie ermöglichen es, benutzerdefinierte, strukturierte Datentypen zu erzeugen. Die Typkonstruktoren erzeugen neue Datentypen durch
Aggregation bestehender Datentypen, ebenso wie Typen im objektorientierten Modell erstellt werden. Im relationalen Modell stehen zusätzlich noch die
beiden Mengen-Typkonstruktoren Tupel“ und Relation“ zur Verfügung.
”
”
Andere Mengen-Typkonstruktoren, wie Liste“ oder Menge“, gibt es im
”
”
Modell hingegen nicht. Die interne Struktur der Datentypen wird gekapselt.
Für den Zugriff auf Objekte eines strukturierten Datentyps werden Methoden
bereitgestellt.
Die so definierten Datentypen können im relationalen Modell als Typ eines
Attributs in einer Relation verwendet werden. Daraufhin können komplex
strukturierte Objekte dieses Typs in dem Attribut gespeichert werden. Für
37
den relationalen Teil des objektrelationalen Modells besteht kein Unterschied
im Vergleich zu Standard-Datentypen. Die in den Attributen gespeicherten
Objekte verhalten sich für das Modell wie ein einziger, skalarer Wert.
Wie bereits gesagt, sind im relationalen Modell die einzelne Datensätze nur
über die gespeicherten Werte identifizierbar. Es gibt im Modell keine eigene Identität, da dies dem Konzept des relationalen Modells widersprechen
würde. Auch im objektrelationalen Modell besitzen die Objekte keine explizite Identität zusätzlich zu den gespeicherten Werten. Eine Identität müsste
also auch hier bei Bedarf, z.B. durch Surrogate, nachgebildet werden.
Bei der Typkonstruktion ist Vererbung anwendbar. Ein Attribut eines bestimmten Typs kann dann ebenfalls Objekte aller Subtypen aufnehmen. Methodenaufrufe werden entsprechend polymorph aufgelöst.
In dem Modell von Date und Darwen wird jedoch im Vergleich zu den Programmiersprachen ein anderes Vererbungsmodell beschrieben. Typen werden
als Mengen aufgefasst. Ein Objekt eines bestimmten Typs gehört zu der Menge des Typs. Ein Subtyp bildet eine Untermenge des Typs.
Der entscheidende Unterschied ist, dass Objekte zur Laufzeit ihren Typ
ändern können. Dies passiert auch automatisch durch die beiden Mechanismen Specialization by Constraint“ und Generalization by Constraint“.
”
”
Subtypen werden durch Einschränkungen (Constraints) beschrieben. Sobald
ein Objekt die Einschränkung erfüllt, gehört es automatisch zum Subtyp und
erhält dann auch den entsprechenden Typ, bzw. wird in die entsprechende
Untermenge einsortiert. Dieses Verfahren nennt sich Specialization by Con”
straint“. Wenn ein Objekt eine Einschränkung nicht mehr erfüllt, erhält es
ebenso automatisch wieder den Supertyp. Dies nennt sich Generalization by
”
Constraint“. Ein Objekt erhält also abhängig vom Zustand den am besten
passenden Typ zugewiesen.
Zur Verdeutlichung wird das Beispiel Kreis und Ellipse verwendet. Ein Kreis
ist eine spezielle Form der Ellipse. Eine Ellipse besitzt zwei Achsen a und
b. Wenn diese beiden Achsen übereinstimmen, erhalten wir einen Kreis mit
Radius r = a = b. Jeder Kreis ist also auch eine Ellipse, bei der die Einschränkung a = b zutrifft. Dadurch wird die Menge aller Ellipsen in zwei
Teilmengen unterteilt: Kreise und nicht kreisförmige Ellipsen.
In dem vorgestellten Vererbungsmodell erhält eine Ellipse automatisch den
Subtyp Kreis, sobald man z.B. durch Zuweisung die beiden Attribute a und
b auf den gleichen Wert setzt. Dies ist die Anwendung von Specialization by
”
Constraint“. Ebenso ändert sich der Typ von Kreis zu Ellipse, sobald einer
38
der beiden Achsen ein Wert zugewiesen wird, der die Einschränkung a = b
verletzt, wenn also a 6= b gesetzt wird.
Es ist zu berücksichtigen, dass im hier vorgestellten objektrelationalen Modell keine Objektidentität und auch keine Referenzen auf Objekte existieren. Verbindungen zwischen Objekten werden, wie im relationalen Modell
üblich, ausschließlich über Fremdschlüssel hergestellt. Objekte werden in den
Attributen einer Relation abgelegt und nur über die relationalen Operatoren zugegriffen. Dieses Vorgehen verhindert Typfehler, die beim Zugriff über
Referenzen auftreten könnten, sobald ein referenziertes Objekt seinen Typ
ändert.
Zur Verdeutlichung wird ein möglicher Typfehler anhand eines Beispiels erklärt. Nehmen wir eine Referenz ref kreis, die den Typ Ref(Kreis) besitzt und
nur Kreise referenzieren darf. Ein beliebiger Kreis k wird durch ref kreis referenziert. Nimmt nun der Kreis aufgrund von Generalization by Constraint“
”
den Typ Ellipse an, würde eine Abfrage des Radius über die Referenz ref kreis
mit einem Typfehler scheitern.
In Tabelle 3.3 auf der nächsten Seite sind die Eigenschaften der drei Modelle
noch einmal in Kurzform gegenübergestellt.
3.4.2
Vor- und Nachteile des objektrelationalen Modells
Das vorgestellte Modell ist eine gelungene Erweiterung des relationalen Modells. Die positiven Eigenschaften bleiben erhalten, wichtige Eigenschaften
der Objektorientierung wurden aufgenommen.
Die wohl wichtigste Erweiterung im objektrelationalen Modell ist die Integration eines erweiterbaren Typsystems, das die Modellierung komplexer
Datentypen erlaubt. Entitäten aus dem Anwendungsgebiet lassen sich so wesentlich besser modellieren und in der Datenbank ablegen.
Einige objektorientierte Konzepte werden jedoch in einer Form integriert, die
sich stark von der Umsetzung in den Programmiersprachen unterscheidet.
Einige Unterschiede sind:
• Die Typkonstruktoren Tupel“ und Relation“ gibt es nicht im objek”
”
torientierten Modell.
• Mengen-Typkonstruktoren, wie Liste“ und Menge“, gibt es nicht im
”
”
objektrelationalen Modell.
39
objektorientiertes
Modell
verhaltensorientierte
Modellierung
imperatives
Paradigma
erweiterbares
Typsystem
Vererbung
Polymorphie
Objekte mit
unveränderlichem Typ
Objektidentität
unabhängig
von Werten
Verknüpfung durch
Referenzen
Objekte
frei im Speicher
Zugriff durch
Methodenaufrufe
Verarbeitung
einzelner Objekte
Zustand
der Objekte
gekapselt
Methoden an
Objekte gebunden
Konsistenzsicherung
durch Axiome
und Methoden
relationales
Modell
strukturorientierte
Modellierung
ohne Verhalten
deskriptives
Paradigma
Typsystem außerhalb
des Modells
keine Vererbung
keine Polymorphie
keine Objekte
keine Identität
unabhängig
von Werten
Verknüpfung durch
Fremdschlüssel
Daten
in Tabellen
strukturiert
Zugriff durch
rel. Algebra
Verarbeitung
mehrerer Datensätze
Zustand
der Daten
frei zugreifbar
keine Methoden
Konsistenzsicherung
durch Constraints
objektrelationales
Modell
strukturorientierte
Modellierung
(Objekte mit Verhalten)
deskriptives &
imperatives
Paradigma
erweiterbares
Typsystem
Vererbung
Polymorphie
Objekte verändern
ihren Typ
keine Identität
unabhängig
von Werten
Verknüpfung durch
Fremdschlüssel
Daten und Objekte
in Tabellen
strukturiert
Zugriff durch
rel. Algebra
(Methodenaufrufe
in rel. Anfragen)
Verarbeitung
mehrerer Datensätze
Zustand der Daten
frei zugreifbar,
Objekte gekapselt
Methoden an
Objekte gebunden
Konsistenzsicherung
durch Constraints
und Methoden
Tabelle 3.3: Eigenschaften der Modelle im Vergleich
40
• Objekte erhalten im objektrelationalen Modell keine eigene Identität,
wie im objektorientierten Modell. Ein konkretes Objekt wird als Wert
betrachtet und allein über den Zustand identifiziert.
• Da Objekte keine Identität haben, können sie auch nicht referenziert
werden. Ein Objekt kann jedoch über Fremdschlüssel referenziert werden. Ebenso kann ein Objekt selbst Fremdschlüssel aufnehmen, um so
auf andere Daten oder Objekte zu verweisen.
• Im objektorientierten Modell kann ein Objekt zur Laufzeit seinen Typ
nicht verändern, im objektrelationalen Modell hingegen schon.
• Die Konzepte Specialization by Constraint“ und Generalization by
”
”
Constraint“ gibt es im objektorientierten Modell ebenfalls nicht.
• Beim objektorientierten Modell werden Objekte frei im Arbeitsspeicher erzeugt und über Referenzen angesprochen. Im objektrelationalen
Modell werden die Objekte in Relationen strukturiert, so dass mittels
relationaler Anfragen darauf zugegriffen werden kann.
Eine Objekt-Struktur im objektorientierten Modell kann daher nicht 1:1 auf
eine objektrelationale Struktur abgebildet werden. Objekte müssen zusätzlich
in Relationen strukturiert werden und Referenzen werden im objektrelationalen Modell nicht unterstützt. Die Objekte werden daher einzeln jeweils in
einem Attribut gespeichert und die Verbindungen zwischen den Objekten
werden über Fremdschlüssel hergestellt.
3.5
Auswertung
Die bestehenden konzeptionellen Differenzen zwischen dem objektorientierten und dem relationalen Modell verursachen einen erheblichen ZusatzAufwand beim gemeinsamen Einsatz der beiden Modelle. Durch Anpassung
der Modelle können die Differenzen jedoch deutlich verringert werden, wodurch auch der verursachte Aufwand gesenkt werden kann.
Das objektrelationale Modell übernimmt wichtige objektorientierte Konzepte
in das relationale Modell. Das relationale Modell wurde dabei ausschließlich
erweitert, die bestehenden Konzepte bleiben unverändert erhalten. Es wurde
besonderes Gewicht darauf gelegt, ein in sich schlüssiges und konsistentes
Modell zu erstellen. Der Schwerpunkt liegt dabei weiterhin auf der Datenmodellierung. Die Modellierung von Verhalten und Algorithmen erhält kaum
Aufmerksamkeit.
Die Umsetzung der objektorientierten Konzepte im objektrelationalen Mo41
dell unterscheidet sich zum Teil deutlich von der Umsetzung in den Programmiersprachen. Ein Zusammenführen des relationalen und des objektorientierten Modells, wie es von den Programmiersprachen genutzt wird, ist
offensichtlich nicht das Hauptziel beim Erstellen des objektrelationalen Modells gewesen.
Insbesondere das Konzept der Identität, wie es im objektorientierten Modell
existiert, ist mit dem relationalen Grundgerüst nicht vereinbar, da Daten im
relationalen Modell einzig und allein anhand von Werten identifiziert und
verknüpft werden. Durch die Vermeidung von Referenzen soll das Modell
einfach und verständlich bleiben.
Es bestehen weiterhin große Unterschiede zwischen dem objektorientierten
und dem objektrelationalen Modell. Eine deutliche Annäherung hat jedoch
dadurch stattgefunden, dass im objektrelationalen Modell ebenfalls neue Datentypen definiert werden können.
Eine echte Integration der Modelle zu einem gemeinsamen Modell findet nicht
statt. Das Zusammenspiel der beiden Modelle wird leider ebenfalls nicht betrachtet. In der Praxis ist jedoch gerade der gemeinsame Einsatz der unterschiedlichen Modelle von Programmiersprache und Datenbank das eigentliche
Problem.
Nachdem das objektrelationale Modell konzeptionell betrachtet wurde, soll
im nächsten Kapitel untersucht werden, wie die praktische Umsetzung in den
Datenbanken realisiert ist.
42
Kapitel 4
Umsetzung
Im vorangegangenen Kapitel wurde das objektrelationale Modell von Date
und Darwen vorgestellt. Für die praktische Umsetzung objektrelationaler Erweiterungen in den Datenbanken hat jedoch der aktuelle SQL:1999-Standard
ein wesentlich größeres Gewicht. Dieser SQL-Standard wurde zwar durch das
Modell beeinflusst, unterscheidet sich jedoch in einigen Punkten.
Die Erweiterung der relationalen Datenbanken hat den Vorteil, dass eine
Kompatibilität zu den relationalen Datenbanken gewahrt bleibt. Die Eigenschaften bestehender Datenbanken, wie z.B. gute Leistung, hohe Stabilität, ausgefeilte Sicherheitsfunktionen sowie Umgang mit großen Datenmengen und komplexen Suchanfragen, bleiben erhalten. Zusätzlich werden die
Möglichkeiten der Objektorientierung zur Verfügung gestellt.
Dadurch ist es möglich, die zusätzlichen Eigenschaften schrittweise zu nutzen. Es muss also nicht mit einem Mal auf ein ganz neues Datenbanksystem
gewechselt werden, was beispielsweise beim Einsatz von objektorientierten
Datenbanken der Fall ist. Insbesondere dann, wenn mehrere Anwendungen
gemeinsam auf eine Datenbasis zugreifen, gestaltet sich ein Wechsel der zugrundeliegenden Datenbank-Technologie als aufwendig, da alle Anwendungen
gleichzeitig umgestellt werden müssen. Zudem stellt die Umstellung von Altsystemen ein besonderes Risiko dar. Da die objektrelationalen Datenbanken
eine Erweiterung der relationalen Datenbanken sind, bleiben die oben geschilderten positiven Charakteristika dieser Datenbanken erhalten. Die vorgeschlagenen Erweiterungen sind im neuen SQL-Standard (SQL:1999) festgelegt worden, so dass weiterhin größtenteils herstellerunabhängig auf die Datenbanken zugegriffen werden kann. Zudem haben alle namhaften Hersteller
von relationalen Datenbanken die neuen Funktionen in ihre Datenbanken aufgenommen oder sind noch dabei, dies zu tun. Somit überträgt sich der große
Marktanteil der relationalen Datenbanken direkt auf die objektrelationalen
43
Datenbanken. Die jahrelange Erfahrung mit relationalen Datenbanken, sowohl bei den Entwicklern, als auch bei den Administratoren, bleibt weiterhin
anwendbar.
Der Vorteil, langsam auf die neue Technologie migrieren zu können, birgt
jedoch auch den Nachteil, dass diese Migration unter Umständen zu langsam
oder gar nicht stattfindet. So können Mischformen über lange Zeit bestehen
bleiben. Beim Einsatz einer ganz neuen Technologie ist dies hingegen nicht
möglich.
4.1
SQL:1999-Standard
Im neuen SQL:1999-Standard wurden vor allem die folgenden objektorientierten Erweiterungen in SQL aufgenommen:
• Benutzerdefinierte Datentypen
• Binden von Methoden an benutzerdefinierte Datentypen
• getypte Tabellen mit Objektidentität und Referenzen
• Tabellenhierarchien
Benutzerdefinierte Datentypen können durch Aggregation beliebiger Datentypen erstellt werden. Zusätzlich wurde der Mengen-Typkonstruktor Array“
”
definiert. Die Typkonstruktoren Tupel“ und Relation“, die im objektrela”
”
tionalen Modell eingeführt wurden, gibt es hingegen nicht.
An die Datentypen können Methoden gebunden werden. Zusätzlich zu benutzerdefinierten Methoden erhält jeder Datentyp automatisch Methoden
zum Lesen und Setzen der Attribute, sowie Konstruktoren zum Erzeugen
von neuen Objekten. Methoden verändern Objekte nur im Speicher. Sollen
Veränderungen permanent erhalten bleiben, muss das veränderte Objekt explizit in der Datenbank gespeichert werden.
Benutzerdefinierte Datentypen können an zwei unterschiedlichen Stellen eingesetzt werden: Zum einen können sie als Datentyp von Attributen innerhalb
einer Tabelle verwendet werden, zum anderen können getypte Tabellen damit
erstellt werden.
Wird der Datentyp einem Attribut zugewiesen, kann dieses Objekte diesen
Typs aufnehmen. Dies entspricht in etwa der Definition im objektrelationalen
Modell von Date und Darwen. Es gilt jedoch die Einschränkung, dass nur
Objekte des exakt selben Typs in dem Attribut abgelegt werden können.
44
Objekte eines Subtyps können in dem Attribut nicht gespeichert werden.
Polymorphie wird hierbei also nicht unterstützt.
Beim Erzeugen einer getypten Tabelle ergibt sich die Tabellendefinition aus
dem Datentyp. Für jedes im Datentyp definierte Attribut wird eine Spalte
in der Tabelle erzeugt. Hinzu kommt immer noch eine zusätzliche Spalte,
die eine Objektidentität aufnimmt. Beim Einfügen eines neuen Objekts in
die Tabelle muss der Wert dieser Spalte einmalig gesetzt werden. Er kann
danach nicht wieder verändert werden. Dieses Vorgehen ist mit einem Surrogat vergleichbar. Je Zeile der Tabelle kann somit genau ein Objekt des Typs
gespeichert werden.
Auch hier gilt, dass nur Objekte gespeichert werden können, die im Typ exakt
mit dem Typ der Tabelle übereinstimmen. Objekte eines Subtyps können
auch hier nicht gespeichert werden.
Die Objektidentität wird verwendet, um Objekte in der Tabelle zu referenzieren. Zum Erstellen von Referenzen wird der Typkonstruktor Ref“ bereit”
gestellt. Damit können Attribute definiert werden, die eine Referenz auf ein
Objekt eines bestimmten Typs aufnehmen können. Auf ein referenziertes Objekt kann durch Dereferenzierung der Referenz zugegriffen werden. Zusätzlich
muss jedoch die Tabelle angegeben werden, in der das referenzierte Objekt
liegt. Dies kann entweder bei jedem Zugriff geschehen, oder aber für eine
Tabelle pauschal festgelegt werden.
Wie bereits beschrieben, können in getypten Tabellen nur Objekte des exakt
selben Typs abgelegt werden. Damit entfällt jedoch ein entscheidendes Element der Objektorientierung: Der polymorphe Zugriff auf Objekte, deren Typen in einer Vererbungsbeziehung stehen. Um dies dennoch zu ermöglichen,
wurden Tabellenhierarchien in den Standard aufgenommen. Eine Tabellenhierarchie verbindet mehrere Tabellen untereinander. Die Tabellen müssen
alle getypt sein und die Typen müssen in einer Vererbungsbeziehung stehen. Wenn auf eine Tabelle einer Tabellenhierarchie zugegriffen wird, werden
gleichzeitig alle Objekte aller Sub-Tabellen mit angesprochen. Sie erscheinen
polymorph in der Anfrage.
4.2
SQL:1999 Beispiel
Es wird nun an einem Beispiel verdeutlicht, wie die neuen Funktionen des
SQL:1999-Standards realisiert sind und wie sie eingesetzt werden können.
Nehmen wir an, wir definieren einen strukturierten Datentyp mit Namen
Adress t“ mit den zwei Attributen Straße“ und Ort“. Beide Attribute
”
”
”
45
sind vom Typ varchar mit Größe 100, so dass darin Texte mit einer Länge
von bis zu 100 Zeichen gespeichert werden können. In Abbildung 4.1 wird
die korrekte SQL:1999 Syntax für die Erzeugung des Typs gezeigt.
Typbezeichner werden als Konvention immer mit t“ abgeschlossen.
”
create type Adress t as (
Straße varchar(100),
Ort varchar(100)
)
Abbildung 4.1: SQL-Beispiel: Erzeugen eines strukturierten Datentyps
Nun ist es möglich, eine Tabelle mit Attributen vom Typ Adress t“ zu
”
definieren. In Abbildung 4.2 ist auch hierfür die korrekte SQL-Schreibweise
angegeben.
create table Person (
Name varchar(100),
Adresse Adress t
)
Abbildung 4.2: SQL-Beispiel: Erzeugen einer Tabelle
Daraus resultierend, ergibt sich Tabelle 4.1.
Name
Monika Schmidt
Peter Petersen
Maria Müller
Adresse
Rübenstraße 103 Freiburg
Borgweg 23
Hamburg
Waldweg 12b
Bremen
Tabelle 4.1: Tabelle Person“ mit einem Attribut vom Typ Adress t“
”
”
Auf die Elemente in der Adresse“-Spalte, die vom strukturierten Daten”
typ Adress t sind, kann nicht direkt zugegriffen werden. Damit die Attribute
trotzdem abgefragt und verändert werden können, werden von der Datenbank automatisch je Attribut zwei Zugriffsmethoden generiert, die den gleichen Namen tragen, wie das Attribut selbst. Eine abfragende Methode ohne
Parameter liefert den momentanen Inhalt des Attributs als Rückgabewert.
Eine modifizierende Methode hat einen Parameter mit demselben Typ wie
das Attribut selbst und setzt den Inhalt des Attributs auf den übergebenen
Wert. Das veränderte Objekt wird dann als Rückgabewert geliefert.
46
Zum Aufruf der Methoden wird die in SQL:1999 eingeführte ..“-Notation
”
verwendet. Bei den Abfragefunktionen ohne Parameter können die Klammern der Einfachheit halber weggelassen werden. Eine mögliche Abfrage der
in der Tabelle Person“ enthaltenen Daten wird in Abbildung 4.3 gezeigt.
”
select Name, Adresse..Straße, Adresse..Ort from Person
Abbildung 4.3: SQL-Beispiel: Abfragen einer Tabelle mit Adress t“-Attribut
”
Die Abfrage aus Abbildung 4.3 liefert als Ergebnis die Tabelle 4.2.
Name
Monika Schmidt
Peter Petersen
Maria Müller
Adresse..Straße
Rübenstraße 103
Borgweg 23
Waldweg 12b
Adresse..Ort
Freiburg
Hamburg
Bremen
Tabelle 4.2: Abfrageergebnis von Tabelle Person“
”
Wie bereits erwähnt wurde, können auch getypte Tabellen erzeugt werden.
Die korrekte SQL:1999 Syntax zur Erstellung einer Tabelle Adressen“ vom
”
Typ Adress t ist in Abbildung 4.4 aufgeführt.
create table Adressen of Adress t ( ref is ObjId user generated )
Abbildung 4.4: SQL-Beispiel: Erzeugen einer getypten Tabelle
Über den hinteren Teil der Anweisung wird festgelegt, wie das Attribut
heißt, das die Objektidentität (OID) aufnehmen soll. In diesem Fall wurde
es ObjId“ benannt. Zudem wurde festgelegt, dass die Objektidentität beim
”
Einfügen von neuen Objekten manuell erzeugt werden muss. Die hier verwendete Datenbank DB2 liefert zum jetzigen Zeitpunkt noch keine Möglichkeit,
OID’s vollständig automatisch zu erzeugen. Die Datenbank liefert jedoch
Funktionen, um eindeutige Zahlenwerte zu generieren, die dann als OID verwendet werden können.
Aus der Anweisung in Abbildung 4.4 ergibt sich die Tabelle 4.3 auf der
nächsten Seite.
Auf die einzelnen Spalten dieser Tabelle kann nun genauso zugegriffen werden wie bei einer ungetypten Tabelle. Wie bereits erwähnt wurde, wird die
Objektidentität verwendet, um Referenzen auf diese Objekte herzustellen.
Dazu wird in einer anderen Tabelle ein Referenz-Attribut definiert. Um mit
47
ObjId
38388822
12833421
83733633
Straße
Rübenstraße 103
Borgweg 23
Waldweg 12b
Ort
Freiburg
Hamburg
Bremen
Tabelle 4.3: Tabelle Adressen“ vom Typ Adress t“
”
”
Referenzen umgehen zu können, wurde im SQL:1999-Standard das Schlüsselwort ref“ eingeführt. Es wird in der Definition eines Attributs verwendet,
”
um ein Referenz-Attribut zu erzeugen. Zudem werden zu jedem Typ automatisch die beiden Funktionen ref“ und deref“ erzeugt. Die ref-Funktion
”
”
bekommt als Parameter ein Objekt vom zugehörigen Typ übergeben und liefert eine getypte Referenz auf dieses Objekt zurück. Die deref-Funktion ist
invers dazu. Ihr wird als Argument eine Referenz übergeben und sie liefert
als Ergebnis das referenzierte Objekt.
In Abbildung 4.5 wird eine Tabelle mit einem Referenz-Attribut auf ein Objekt vom Typ Adress t definiert.
create table Person2 (
Name varchar(100),
Adresse ref(Adress t)
)
Abbildung 4.5: SQL-Beispiel: Erzeugen einer Tabelle mit Referenz-Attribut
In der resultierenden Tabelle 4.4 werden in der Adresse-Spalte Referenzen
auf Objekte vom Typ Adress t abgelegt.
Person2“-Tabelle
”
Name
Monika Schmidt
Peter Petersen
Maria Müller
Thomas Berger
Adresse
38388822
12833421
83733633
83733633
Adressen“-Tabelle
”
ObjId
Straße
38388822 Rübenstraße 103
12833421 Borgweg 23
83733633 Waldweg 12b
Ort
Freiburg
Hamburg
Bremen
Tabelle 4.4: Tabelle Person2“ mit Referenz-Attribut
”
Die Referenzen werden über Zahlencodes realisiert und intern wie Fremdschlüssel behandelt. Der Vorteil gegenüber Fremdschlüsseln ist jedoch, dass
die Referenzen direkt verfolgt werden können. Dazu wurde im SQL:1999Standard die –>“-Notation eingeführt.
”
48
Damit der Zugriff auf die Referenzen funktioniert, muss der Datenbank jedoch mitgeteilt werden, in welcher Tabelle die referenzierten Objekte liegen.
Dazu dient die scope“-Anweisung. Um die Referenzen der Tabelle Person2“
”
”
nutzen zu können, verändern wir die Tabelle indem wir einen scope“ hin”
zufügen, der das Attribut Adresse“ mit der Tabelle Adressen“ verknüpft.
”
”
Abbildung 4.6 zeigt die benötigte SQL-Anweisung dafür.
alter table Person2 alter Adresse add scope Adressen
Abbildung 4.6: SQL-Beispiel: Festlegen des scopes“ einer Referenz
”
Jetzt kann auf die Referenz in der Tabelle Person2“ zugegriffen werden.
”
Eine Abfrage der gespeicherten Person mit der zugehörigen Adresse wird in
Abbildung 4.7 gezeigt.
select Name, Adresse–>Straße, Adresse–>Ort from Person2
Abbildung 4.7: SQL-Beispiel: Abfragen einer Tabelle mit Referenz-Attribut
Das Ergebnis der Abfrage aus Abbildung 4.7 ist in Tabelle 4.5 zu sehen.
Name
Monika Schmidt
Peter Petersen
Maria Müller
Thomas Berger
Adresse–>Straße
Rübenstraße 103
Borgweg 23
Waldweg 12b
Waldweg 12b
Adresse–>Ort
Freiburg
Hamburg
Bremen
Bremen
Tabelle 4.5: Abfrageergebnis von Tabelle Person2“
”
Das Ergebnis unterscheidet sich nicht von dem Abfrageergebnis einer Tabelle
mit eingebettetem Objekt, wie es in Tabelle 4.2 auf Seite 47 zu sehen war.
Der Unterschied besteht jedoch darin, dass mehrere Personen in der Tabelle
Person2“ auf dieselbe Adresse in der Tabelle Adressen“ verweisen können.
”
”
Bei dem obigen Beispiel verweisen die Referenzen der beiden Personen Maria
”
Müller“ und Thomas Berger“ auf dieselbe Adresse.
”
In den vorhergehenden Ausführungen wurde gezeigt, wie Datentypen erzeugt werden, wie Tabellen angelegt werden und wie Daten abgefragt werden. Im Folgenden soll darauf eingegangen werden, wie Daten eingefügt und
verändert werden.
Beim Einfügen in Tabellen mit eingebetteten Objekten muss zuerst ein entsprechendes Objekt erzeugt und dann eingefügt werden. Zum Erzeugen eines
49
leeren Objekts stellt die Datenbank zu jedem Datentyp automatisch eine
Konstruktor-Funktion bereit. Diese trägt den gleichen Namen wie der Datentyp selbst. Der Aufruf dieser Funktion liefert ein leeres Objekt dieses
Datentyps zurück. An diesem können modifizierende Methoden aufgerufen
werden, um die Attribute des Datentyps auf die gewünschten Werte zu setzen. Zur Vereinfachung kann das Erzeugen und Verändern des Objekts in
einer Anweisung kombiniert werden. In Abbildung 4.8 ist die nötige SQLAnweisung aufgeführt.
insert into Person ( Name, Adresse ) values (
’Stefan Meier’,
Adress t()..Straße( ’Eichweg 23’ )..Ort( ’Berlin’ )
)
Abbildung 4.8: SQL-Beispiel: Einfügen eines Eintrags in Tabelle Person“
”
Das zweite Attribut der Tabelle Person“ ist vom Typ Adress t“. Mit dem
”
”
Aufruf der Konstruktor-Funktion namens Adress t()“ wird ein leeres Objekt
”
dieses Typs erzeugt. Innerhalb derselben Anweisung werden nun die beiden
Funktionen Straße“ und Ort“ mit jeweils einem entsprechenden Argument
”
”
aufgerufen. Danach stehen die in Tabelle 4.6 gezeigten Informationen in der
Datenbank.
Name
Monika Schmidt
Peter Petersen
Maria Müller
Stefan Meier
Adresse
Rübenstraße 103
Borgweg 23
Waldweg 12b
Eichweg 23
Freiburg
Hamburg
Bremen
Berlin
Tabelle 4.6: Tabelle Person“ mit zusätzlichem Eintrag
”
Um einen bestehenden Eintrag in der Tabelle zu verändern, verwendet man
ebenfalls die modifizierenden Funktionen. Das modifizierte Objekt wird mittels eines SQL Update-Befehls in die Datenbank zurück geschrieben. In Abbildung 4.9 ist dafür ein Beispiel zu sehen.
update Person set Adresse = Adresse..Straße( ’Neuer Weg 3’ )
where Name = ’Monika Schmidt’
Abbildung 4.9: SQL-Beispiel: Ändern eines Eintrags in der Tabelle Person“
”
50
Mittels der where“-Klausel wird der zu ändernde Eintrag eingeschränkt. An
”
der Adresse dieses Eintrags wird die modifizierende Funktion Straße“ mit
”
dem Attribut Neuer Weg 3“ aufgerufen. Als Ergebnis liefert diese Funktion
”
das veränderte Objekt zurück, das der Adresse wieder zugewiesen wird. Nach
dieser Operation enthält die Datenbank die in Tabelle 4.7 gezeigten Daten.
Name
Monika Schmidt
Peter Petersen
Maria Müller
Stefan Meier
Adresse
Neuer Weg 3 Freiburg
Borgweg 23
Hamburg
Waldweg 12b
Bremen
Eichweg 23
Berlin
Tabelle 4.7: Tabelle Person“ mit geändertem Eintrag
”
Das Einfügen und Verändern von Daten in getypten Tabellen funktioniert
genauso wie bei normalen, ungetypten Tabellen. Die SQL-Befehle Insert“
”
und Update“ werden wie gewohnt angewendet. Beim Einfügen in einer ge”
typten Tabelle muss jedoch zusätzlich die Objektidentität (OID) gesetzt werden. Die OIDs müssen innerhalb einer Tabelle immer eindeutig sein. Es gibt
verschiedene Möglichkeiten, dies zu gewährleisten. Zum einen kann die Software, die auf die Datenbank zugreift, die OIDs eigenständig erzeugen. Bei
gleichzeitigem Zugriff mehrerer Benutzer kann es jedoch schwierig werden sicherzustellen, dass keine Nummern mehrfach vergeben werden. Eine andere
Möglichkeit ist, die OIDs mit Hilfe einer Datenbankfunktion erzeugen zu lassen, die eindeutige OIDs liefern kann. Bei der hier angewendeten Datenbank
DB2 steht die Funktion generate unique()“ dafür zur Verfügung.
”
Stattdessen lässt sich auch eine so genannte Sequence“ verwenden. Eine
”
Sequence kann in der Datenbank angelegt werden und liefert daraufhin bei
jeder Abfrage den nächsten Eintrag einer Reihe von Zahlen. Da Sequence“
”
momentan noch nicht von DB2 unterstützt wird, wird hier die genera”
te unique()“ Funktion angewendet.
Es ist möglich, direkt beim Einfügen von Daten eine OID erzeugen zu lassen.
Wie das funktioniert, ist in Abbildung 4.10 auf der nächsten Seite aufgeschrieben.
Hier wird der Konstruktorfunktion Adress t()“ eine eindeutige ID überge”
ben. Die daraus resultierende OID ist an den Typ Adress t gebunden. Die
Objektidentität ist also neben ihrer Eindeutigkeit zudem typgebunden.
Wenn nun in einer anderen Tabelle eine Referenz auf die gerade eingefügte
Adresse erstellt werden soll, muss die erzeugte OID aus der Tabelle Adres”
51
insert into Adressen ( ObjId, Straße, Ort ) values (
Adress t( generate unique() ),
’Eichweg 23’,
’Berlin’
)
Abbildung 4.10: SQL-Beispiel: Einfügen eines Eintrags in Adressen“
”
sen“ dort als Referenz verwendet werden. Dies kann beispielsweise durch eine
eingebettete Select-Anweisung geschehen, wie in Abbildung 4.11 zu sehen ist.
insert into Person2 ( Name, Adresse ) values (
’Stefan Meier’,
( select ObjId from Adressen
where Straße = ’Eichweg 23’ and Ort = ’Berlin’ )
)
Abbildung 4.11: SQL-Beispiel: Einfügen eines Eintrags in Tabelle Person2“
”
Die eingebettete Select-Anweisung hat jedoch den Nachteil, dass der zu verknüpfende Eintrag im Select genau spezifiziert werden muss. Wenn die SelectAnweisung nicht eindeutig ist, da z.B. zweimal die gleiche Adresse in der
Tabelle eingetragen ist, ist es nicht möglich, diese beiden Einträge auseinander zu halten. Da die eingebettete Select-Anweisung in diesem Fall zwei
Einträge als Ergebnis liefert und die Datenbank nicht erkennen kann, welcher
der richtige ist, führt dies zu einer Fehlermeldung.
Um dies zu vermeiden, ist es besser, zuerst eine OID zu generieren und
diese dann beim Einfügen der Daten zu verwenden. Zum Erzeugen der
OID können Funktionen der Datenbank genutzt werden. Das ist vor allem dann ratsam, wenn die Adress- und die Personen-Daten direkt hintereinander eingefügt werden sollen. Damit wird zudem sichergestellt, dass
die richtigen Einträge referenziert werden. Wenn die OID bekannt ist, wird
sie in der Insert-Anweisung für die Adressen“-Tabelle anstelle der ge”
”
nerate unique()“-Funktion eingefügt, sie wird also als Parameter an die
Adress t()“-Konstruktorfunktion übergeben. Bei der Insert-Anweisung für
”
die Person2“-Tabelle wird anstelle der eingebetteten Select-Anweisung das”
selbe Konstrukt verwendet, also wird auch hier die OID als Argument an
die Konstruktorfunktion übergeben. Die korrekte SQL-Syntax für die beiden
Anweisungen findet sich in Abbildung 4.12 auf der nächsten Seite.
Der erste Eintrag fügt eine neue Adresse in die Tabelle Adressen“ ein. Dabei
”
wird eine zuvor erzeugte OID verwendet. Nachdem die Adresse eingef ügt
52
insert into Adressen ( ObjId, Straße, Ort ) values (
Adress t( ’48837221’ ),
’Eichweg 23’,
’Berlin’
)
insert into Person2 ( Name, Adresse ) values (
’Stefan Meier’,
Adress t( ’48837221’ )
)
Abbildung 4.12: SQL-Beispiel: Einfügen zweier Einträge mit bekannter OID
wurde, wird eine Person in die Tabelle Person2“ eingetragen. Bei dieser
”
Person wird eine Referenz auf die gerade erzeugte Adresse abgelegt, indem
auch hier dieselbe OID verwendet wird. Daraufhin kann von der Person aus
über die Referenz auf die Adresse zugegriffen werden, wie in Abbildung 4.7
auf Seite 49 zu sehen war.
Es muss jedoch beachtet werden, dass Referenzen nicht automatisch durch
die Datenbank überprüft werden. Deswegen kann eine Referenz eingetragen
werden, zu der gar kein Objekt existiert. Ebenso ist es möglich, ein Objekt
zu löschen, das noch referenziert wird. In diesen beiden Fällen entstehen so
genannte hängende Referenzen“. Wenn versucht wird, über eine hängen”
de Referenz auf ein Objekt zuzugreifen, liefert die Datenbank einen Fehler
zurück. Hängende Referenzen können verhindert werden, indem man in der
Datenbank zusätzliche Constraints definiert. Dadurch kann z.B. das Löschen
eines Eintrags, auf den noch referenziert wird, verhindert werden. Ebenso
können sie verhindern, dass eine Referenz eingetragen wird, zu der es gar
kein Objekt gibt. Die Verwendungsmöglichkeiten von Constraints variieren
zwischen den verschiedenen Datenbank-Herstellern.
Zusätzlich zu den bisher gezeigten Erweiterungen können Datentypen in
Typhierarchien zusammengefasst werden. Dies verhält sich analog zur Vererbung bei Programmiersprachen. Ein Subtyp erbt alle Attribute und Methoden des Supertyps und kann weitere eigene Attribute und Methoden hinzufügen. Ebenso können die bestehenden Methoden überschrieben werden.
Auf die Objekte des Subtyps kann in einer Select-Anfrage polymorph zugegriffen werden. Bei der DB2 Datenbank von IBM funktioniert zum aktuellen
Zeitpunkt die polymorphe Auflösung von Methodenaufrufen noch nicht automatisch und muss deswegen von Hand umgesetzt werden. Die Realisierung
soll aber in einer der nächsten Versionen nachgeholt werden. Um die Objekte
53
polymorph selektieren zu können, werden Tabellenhierarchien verwendet.
Wenn ein Attribut eines bestimmten Typs in einer Tabelle definiert wurde,
können dort nur Objekte genau dieses Typs abgelegt werden. Gleiches gilt bei
getypten Tabellen. Auch dort können nur Objekte abgelegt werden, die im
Typ exakt übereinstimmen. Es ist jedoch möglich, mehrere Tabellen in einer
so genannten Tabellenhierarchie zu verbinden. Dafür müssen alle Tabellen
der Hierarchie getypt sein und zudem müssen alle diese Typen zu einer Typhierarchie gehören. Darüber hinaus muss die Tabellenhierarchie kovariant
zur Vererbungshierarchie verlaufen. Das bedeutet, dass einer Tabelle eines
bestimmten Typs nur Sub-Tabellen zugeordnet werden können, die durch
einen Subtyp dieses Typs definiert werden. Wenn auf eine Tabelle einer Tabellenhierarchie zugegriffen wird, wird automatisch auf alle Elemente aller
Sub-Tabellen mit zugegriffen. Bei einer Anfrage an eine Super-Tabelle erhält
man dadurch polymorph den Zugriff auf die Elemente aller Sub-Tabellen
dieser Tabelle.
Zum Erstellen einer Tabellenhierarchie wird zuerst eine Typhierarchie
benötigt. In Abbildung 4.13 wird zum Typ Adress t“ ein Subtyp Plz”
”
Adress t“ definiert, der eine Adresse um eine Postleitzahl erweitert. F ür die
Definition von Subtypen wurde im SQL-Standard das Schlüsselwort under“
”
eingeführt.
create type PlzAdress t under Adress t as (
Plz varchar(10)
)
Abbildung 4.13: SQL-Beispiel: Erzeugen eines Subtyps
Der erzeugte Typ hat nun drei Attribute. Zwei vom Supertyp Adress t geerbte Attribute, Straße“ und Ort“, und das hinzugefügte Attribut Plz“,
”
”
”
um die Postleitzahl aufzunehmen. Damit ist es möglich, eine Sub-Tabelle
von Adressen zu erzeugen, die diesen Typ zugewiesen bekommt. Der dafür
benötigte SQL-Befehl ist in Abbildung 4.14 zu sehen.
create table PlzAdressen of PlzAdress t under Adressen
inherit select privileges
Abbildung 4.14: SQL-Beispiel: Erzeugen einer Sub-Tabelle
Der Befehl inherit select privileges“ muss angegeben werden und stellt si”
cher, dass bei einer Select-Anweisung die Zugriffsrechte auf die Sub-Tabellen
54
korrekt übernommen werden. Tabelle 4.8 zeigt die Form der erzeugten Tabelle.
ObjId
Straße
29955432 Teichweg 44
99282834 Frankring 8
Ort
Bamberg
Jena
Plz
54422
40155
Tabelle 4.8: Tabelle PlzAdressen“ vom Typ PlzAdress t“
”
”
Wie bereits erwähnt, wird bei einem Zugriff auf die Super-Tabelle Adressen“
”
auch auf die Elemente der Sub-Tabellen zugegriffen. Eine Select-Anweisung
aller Attribute der Tabelle Adressen“ liefert damit das Ergebnis in Tabel”
le 4.9.
ObjId
38388822
12833421
83733633
29955432
99282834
Straße
Rübenstraße 103
Borgweg 23
Waldweg 12b
Teichweg 44
Frankring 8
Ort
Freiburg
Hamburg
Bremen
Bamberg
Jena
<–
<–
<–
<–
<–
aus
aus
aus
aus
aus
Adressen
Adressen
Adressen
PlzAdressen
PlzAdressen
Tabelle 4.9: Ergebnis des Befehls: Select * from Adressen“
”
Mit der Funktion outer“ kann man erreichen, dass die Attribute aller Sub”
Tabellen eingeblendet werden. Die Funktion erwartet die abzufragende Tabelle als Parameter und liefert als Ergebnis eine neue Tabelle, die um die
Attribute aller Sub-Tabellen erweitert wurde. Die zusätzlich eingeblendeten
Attribute der Sub-Tabellen werden bei allen Einträgen, die dieses Attribut
nicht besitzen, mit null“ gefüllt. Die outer“-Funktion kann im From“-Teil
”
”
”
einer Select-Anweisung verwendet werden.
Auf gleiche Weise kann die Funktion only“ verwendet werden, um eine An”
frage auf die Elemente genau einer Tabelle einzuschränken. Es werden dann
keine Elemente aus den Sub-Tabellen der Tabellenhierarchie angezeigt.
In SQL:1999 wird außerdem der Mengen-Konstruktor Array“ definiert. Dies
”
wird zur Zeit allerdings noch von den wenigsten Datenbanken unterstützt. Einige Datenbanken unterstützen Mengen-Konstruktoren wie List“ und Set“.
”
”
Diese wurden jedoch bisher nicht in den Standard aufgenommen. Mit den bisher gezeigten Funktionen kann in einem Attribut immer nur genau ein Wert
gespeichert werden. Die Mengen-Konstruktoren ermöglichen es jedoch, in einem Attribut mehrere Werte zu speichern. Abbildung 4.15 auf der nächsten
Seite zeigt die SQL-Syntax für einen Mengen-Konstruktor.
55
create type Person t as (
name varchar(100),
skills array(varchar(100))
)
Abbildung 4.15: SQL-Beispiel: verwenden des Mengen-Konstruktors Array“
”
Daraus ergibt sich ein Datentyp Person t“ mit einem Attribut name“ und
”
”
einem zweiten, mengenwertigen Attribut skills“, welches eine Liste von kur”
zen Texten aufnehmen kann.
4.3
SQLj - objektrelationale Datenbanken
und Java
Mit den beschriebenen Erweiterungen des neuen SQL:1999-Standards können
benutzerdefinierte Datentypen in der Datenbank erstellt und genutzt werden.
Der Standard beschreibt jedoch nicht, wie Objekte der Datenbank mit Objekten der Programmiersprachen ausgetauscht werden können. Die Integration
in die Programmiersprachen beschränkt sich weiterhin auf ein Call Level Interface (CLI), mit dem SQL-Befehle als Strings an die Datenbank geschickt
werden können. Die Objekte der Programmiersprache können dabei jedoch
nicht direkt mit den Objekten der Datenbank ausgetauscht werden. Stattdessen müssen die Objekte bei jedem Zugriff in alle ihre Einzelteile zerlegt
werden. An der Schnittstelle können nur Relationen ausgetauscht werden,
die ausschließlich Attribute mit Standard-Datentypen enthalten.
Um die Kooperation zwischen der Programmiersprache Java und den objektrelationalen Datenbanken zu verbessern hat sich ein Konsortium von
Datenbankherstellern zusammen geschlossen und den SQLj-Standard ausgearbeitet. Der Standard besteht aus drei Teilen:
SQLj Part 0 - Einbetten von statischem SQL in Java Code
SQLj Part 1 - Ausführen von statischen Java Methoden als
Stored Procedure in der Datenbank
SQLj Part 2 - SQLj Types“ - Abbilden von Java Datentypen auf
”
strukturierte Datentypen der Datenbank.
Die ersten beiden Teile (Part 0 und Part 1) sind bereits umgesetzt. Der dritte
Teil (Part 2) wird bisher von keiner Datenbank unterstützt.
Das Einbetten von statischem SQL in Java Code erleichtert vor allem den
56
Umgang mit SQL. Beispielsweise können Variablen leichter zwischen Javaund SQL-Code ausgetauscht werden. Zudem sind zusätzliche Geschwindigkeitssteigerungen möglich, wenn die statischen SQL-Befehle vor dem Programmstart in der Datenbank vorkompiliert werden. Im Folgenden wird jedoch nicht weiter auf diesen Teil des Standards eingegangen, da er den Umgang mit den objektorientierten Erweiterungen nicht beeinflußt.
Dass Stored Procedures, die in der Datenbank ablaufen sollen, in Java programmiert werden können, hat einige Vorteile:
• Zum Erstellen der Stored Procedures steht die volle Mächtigkeit einer
objektorientierten Programmiersprache zur Verfügung.
• Der Softwareentwickler kann durchgängig mit einer, ihm gut bekannten,
Programmiersprache arbeiten.
• Die Programmlogik kann relativ einfach zwischen der ClientAnwendung und dem Datenbank-Server hin- und her verschoben werden.
• Die Java-Methoden können zuerst in einer Client-Anwendung ausprobiert und getestet werden, bevor sie dann in die Datenbank überführt
werden. Dadurch kann beispielsweise die Fehlersuche deutlich erleichtert werden.
Darüber hinaus gibt es keine Unterschiede zu Stored Procedures, die beispielsweise in SQL programmiert wurden.
Mit Hilfe des dritten Teils (Part 2), auch SQLj Types“ genannt, soll es
”
einmal möglich sein, zu einem bestehenden Java Datentyp einen strukturierten Datentyp in der Datenbank zu definieren. Der Datentyp der Datenbank
hat dann vergleichbare Attribute wie der Java Datentyp. Ebenso können die
Methoden des Java Datentyps an den Datentyp der Datenbank gebunden
werden. Objekte der Java-Anwendung können dann direkt mit der Datenbank ausgetauscht werden, ohne dass sie vorher zerlegt oder konvertiert werden müssen. Das Erstellen von Mapping-Code kann dadurch stark reduziert,
wenn nicht ganz vermieden werden.
Die hier verwendete Datenbank DB/2 von IBM bietet noch keine Unterstützung für SQLj Types.
4.4
Auswertung
Der neue SQL:1999-Standard integriert objektorientierte Erweiterungen in
die bestehende relationale Datenbank-Sprache SQL. Dabei werden Konzep57
te wie die Erweiterbarkeit des Typsystems, Vererbung, Objektidentität und
Referenzen aufgenommen, wodurch eine bessere Datenmodellierung möglich
wird. Eine Abwärtskompatibilität zum vorhergehenden SQL-Standard bleibt
gewahrt.
Die Bildung eines in sich schlüssigen objektrelationalen Modells ist offensichtlich nicht das Hauptziel des SQL:1999-Standards. Es scheint vielmehr so, als
stünde die einfache Umsetzbarkeit der eingeführten Konzepte im Vordergrund. Dadurch entstehen Kompromisse, die ein einheitliches, klar strukturiertes Modell verhindern. Wichtige Strukturelemente der Objektorientierung
sind mangelhaft und inkonsistent umgesetzt.
Ein wesentlicher Mangel besteht darin, dass an der Schnittstelle der Datenbank keine Typinformationen von benutzerdefinierten Datentypen bereitgestellt werden. An der SQL-Schnittstelle zur Datenbank werden ausschließlich
Relationen mit Standard-Datentypen als Ergebnis von Anfragen bereitgestellt. Komplexe Datentypen sind an der Schnittstelle nicht möglich. Objekte
müssen daher bei einem Zugriff in ihre einzelnen Attribute zerlegt werden.
Die Typinformation des Objektes geht dabei verloren. Beim Laden oder Speichern von Objekten muss der korrekte Typ manuell abgebildet werden. Die
Typinformation kann nur implizit über den Typ des Attributs bzw. den Typ
der getypten Tabelle ermittelt werden, in dem das Objekte gespeichert ist.
Der eigentliche Datenaustausch mit den objektrelationalen Datenbanken unterscheidet sich daher kaum von dem mit relationalen Datenbanken.
Ebensowenig können Typdefinitionen zwischen einer Programmiersprache
und SQL ausgetauscht werden. Um ein Objekt bestimmten Typs in der Datenbank ablegen zu können, muss ein vergleichbarer SQL-Datentyp manuell
in der Datenbank definiert werden.
Objektidentität und Referenzen werden ebenfalls mangelhaft und inkonsistent unterstützt. Eine Objektidentität ist nur in getypten Tabellen vorhanden. Objekte, die in einem Attribut einer Tabelle eingebettet gespeichert
sind, besitzen keine Identität und sind daher auch nicht direkt referenzierbar. Die Objektidentität ist zudem nicht zwischen Programmiersprache und
Datenbank übertragbar. Eine Abbildung von Objekten im Arbeitsspeicher
auf Objekte in der Datenbank muss daher vollständig manuell programmiert
werden.
Referenzen müssen ebenfalls aufwendig manuell eingetragen und verfolgt werden. Ein automatisches Nachladen von referenzierten Objekten wird nicht
unterstützt. Wenn Objekte, die im Arbeitsspeicher über Referenzen verbunden sind, in der Datenbank abgelegt werden, müssen die Verknüpfungen dort
manuell wieder hergestellt werden.
58
Auch ganze Objektstrukturen, die aus mehreren untereinander verknüpften
Objekten bestehen, können nicht als Ganzes übertragen werden. Statt dessen
müssen alle benötigten Objekte einzeln abgefragt und übertragen werden. Die
Verbindung zwischen den Objekten muss in der Programmiersprache manuell
rekonstruiert werden.
Vererbung und Polymorphie werden ebenfalls unzureichend unterstützt. In
der Datenbank ist es nicht möglich, in einem Attribut eines bestimmten Typs
ebenfalls Objekte eines Subtyps abzulegen, wie es im objektrelationalen Modell von Date und Darwen gefordert wird. Dies erklärt sich auch dadurch,
dass die benötigte Typinformation, welchen konkreten Typ das gespeicherte Objekte besitzt, nicht an die Programmiersprache übertragen wird. Beim
Laden könnte der konkrete Typ des Objekts also nicht rekonstruiert werden.
Polymorphie wird durch Tabellenhierarchien unterstützt. Beim Zugriff auf
eine Super-Tabelle werden auch die Attribute der Sub-Tabellen eingeblendet. Beim Laden der enthaltenen Objekte wird jedoch keine Polymorphie
unterstützt. Die Objekte werden beim Zugriff in ihre Einzelteile zerlegt und
zusammen in einer Tabelle an die Programmiersprache übergeben. Dabei gehen jedoch alle Typinformationen verloren. Der konkrete Typ der einzelnen
Objekte kann in der Programmiersprache nicht rekonstruiert werden.
Es bestehen auch deutliche Unterschiede zum objektrelationalen Modell von
Date und Darwen. Die Grundrichtung ist sehr ähnlich. Die wesentliche Erweiterung im SQL:1999-Standard ist ein erweiterbares Typsystem. Die Details
unterscheiden sich jedoch deutlich. Die Eigenschaften der beiden Modelle
sind in Tabelle 4.10 auf Seite 61 noch einmal tabellarisch gegenüber gestellt.
Getypte Tabellen, Objektidentität und Referenzen sowie Tabellenhierarchien
sind nicht Teil des Modells von Date und Darwen. Diese Elemente werden
hingegen stark von ihnen kritisiert. Die theoretische Basis dieser Elemente ist
nach ihrer Aussage unklar und nicht mit dem relationalen Modell vereinbar
(vgl. [Date, Darwen 00]).
Darüber hinaus wird die Vererbung in den beiden Modellen unterschiedlich
umgesetzt. Das objektrelationale Modell integriert Vererbung und Polymorphismus. Ein Objekt nimmt dabei automatisch zur Laufzeit immer den am
besten passenden Typ an. Objekte werden gekapselt und ausschließlich über
Methoden angesprochen.
Im SQL:1999-Standard wird Vererbung unter Typen unterstützt. Polymorphismus wird jedoch nur sehr eingeschränkt unterstützt. In Attributen wird
Polymorphismus gar nicht unterstützt und bei getypten Tabellen nur bedingt.
Zudem kann auf alle Attribute der Objekte direkt zugegriffen werden.
59
Der SQL:1999-Standard versucht, die Anknüpfung an objektorientierte Programmiersprachen dadurch zu erleichtern, dass objektorientierte Erweiterungen in die Datenbanken integriert werden. Das eigentlich Problem, nämlich
die mangelhafte Verknüpfung von Datenbank und Programmiersprache, wird
dabei leider vernachlässigt.
60
objektrelationales
Modell
strukturorientierte
Modellierung
(Objekte mit Verhalten)
deskriptives &
imperatives
Paradigma
erweiterbares
Typsystem
Vererbung
Polymorphie
Objekte verändern
ihren Typ
keine Identität
unabhängig
von Werten
Verknüpfung durch
Fremdschlüssel
Daten und Objekte
in Tabellen
strukturiert
Zugriff durch
rel. Algebra
(Methodenaufrufe
in rel. Anfragen)
Verarbeitung
mehrerer Datensätze
Zustand der Daten
frei zugreifbar,
Objekte gekapselt
Methoden an
Objekte gebunden
Konsistenzsicherung
durch Constraints
und Methoden
SQL:1999
Standard
strukturorientierte
Modellierung
(Objekte mit Verhalten)
deskriptives &
imperatives
Paradigma
erweiterbares
Typsystem
Vererbung
Polymorphie
in getypten Tabellen
Objekte mit
unveränderlichem Typ
Objektidentität
unabhängig von Werten
in getypten Tabellen
Verknüpfung durch
Fremdschlüssel,
Referenzen in getypten Tabellen
Daten und Objekte
in Tabellen
strukturiert
Zugriff durch
rel. Algebra
(Methodenaufrufe
in rel. Anfragen)
Verarbeitung
mehrerer Datensätze
Zustand der Daten
und Objekte
frei zugreifbar
Methoden an
Objekte gebunden
Konsistenzsicherung
durch Constraints
und Methoden
Tabelle 4.10: Objektrelationales Modell im Vergleich zu SQL:1999
61
62
Kapitel 5
Konstruktion
Bisher wurde das objektrelationale Modell, sowie dessen Umsetzung im
SQL:1999-Standard vorgestellt. Im Folgenden wird anhand eines Prototyps
konstruktiv demonstriert, wie die objektrelationalen Erweiterungen der Datenbanken in einer objektorientierten Software genutzt werden können. Dabei
steht die Integration und Zusammenarbeit von Datenbank und Programmiersprache im Vordergrund.
5.1
Datenbankmodellierung
Im vorangegangenen Kapitel wurde der neue SQL:1999-Standard dargestellt,
der objektrelationale Erweiterungen in bestehende SQL-Datenbanken integriert. Einige Unterschiede zum objektorientierten Modell bleiben jedoch bestehen. Es entsteht keine Integration zwischen den Datenbanken und den objektorientierten Programmiersprachen. Darüber hinaus wird nicht erläutert,
wie die unterschiedlichen Konzepte im Zusammenhang mit einer objektorientierten Programmiersprache genutzt werden können.
Im Folgenden habe ich zu verschiedenen Konzepten Möglichkeiten erarbeitet,
wie die objektrelationalen Erweiterungen zusammen mit einer objektorientierten Programmiersprache eingesetzt werden können.
1. Wie können Datentypen der Programmiersprache auf Datentypen der Datenbank abgebildet werden?
Zu einem Datentyp der Programmiersprache kann ein vergleichbarer Datentyp in der Datenbank erstellt werden. Zu jedem Attribut des Datentyps der
Programmiersprache wird ein vergleichbares Attribut im Datentyp der Datenbank definiert. Der Datentyp muss jedoch manuell in der Datenbank angelegt werden und kann bisher nicht aus dem Datentyp der Programmiersprache
63
generiert werden. Es ist auch zu berücksichtigen, dass spätere Anpassungen
am Datentyp der Programmiersprache meist Anpassungen in der Datenbank
nach sich ziehen und umgekehrt.
Attribute mit Standard-Datentyp bereiten keine Probleme. Attribute, die
ein anderes Objekt einbetten, sind ebenfalls problemlos möglich. 1-zu-1Beziehungen zwischen Objekten werden auf diese Weise abgebildet. Bei n-zum-Beziehungen werden Objekte hingegen mehrfach referenziert und können
daher nicht eingebettet werden. Der SQL:1999-Standard definiert hierfür die
Objektidentität und Referenzen bei getypten Tabellen.
2. Wie können Objektidentität und Referenzen zwischen Objekten
in der Datenbank abgebildet werden?
Der SQL:1999-Standard definiert für getypte Tabellen eine Objektidentität
und erlaubt Referenzen auf Objekte, die in einer getypten Tabelle abgelegt
sind. Konzeptionell ist die Objektidentität in getypten Tabellen mit Surrogaten vergleichbar, wie sie auch in relationalen Datenbanken eingesetzt werden.
Referenzen sind streng genommen eine Schlüssel-Beziehung, da lediglich der
Wert einer Objektidentität in einer anderen Tabelle als Fremdschlüssel gespeichert wird. Damit auf die Verbindung leichter zugegriffen werden kann,
wurde syntaktisch die –>“-Notation eingeführt. Der Zugriff ist jedoch ge”
nauso mittels einer Join-Operation möglich.
Objekte, die direkt referenziert werden sollen, werden daher in einer getypten
Tabelle abgelegt.
Bei n-zu-1-Beziehungen können Referenzen verwendet werden. 1-zu-nBeziehungen müssen weiterhin über Fremdschlüssel abgebildet werden. Jedoch wird auch hier die Objektidentität genutzt, indem die n Objekte jeweils
die Objektidentität des einen Objektes aufnehmen, das diese Objekte referenziert. Dies ist nötig, da ein Attribut immer nur eine Referenz aufnehmen
kann. Sobald die Datenbanken mengenwertige Attribute unterstützen, sind
auch 1-zu-n-Beziehungen durch Referenzen möglich. Ebenso müssen n-zu-mBeziehungen bisher weiterhin über Verknüpfungstabellen realisiert werden.
Auch dies kann sich mit der Unterstützung von mengenwertigen Attributen
ändern.
3. Können die Methoden eines Datentyps der Programmiersprache
in die Datenbank übernommen werden? Welcher Aufwand ist
damit verbunden und welchen Einfluss haben Methoden auf die
Leistung der Datenbank?
Das Binden von Methoden ist zumindest zum jetzigen Zeitpunkt nicht au64
tomatisch möglich. Stattdessen müssen die Methoden in der Datenbank neu
entwickelt werden, da die Datenbank bestimmte Anforderungen an Methoden
stellt. Es ist jedoch möglich, in der Datenbank eine Methode zu erstellen, die
für die Umsetzung ihrer Aufgabe auf die ursprüngliche Methode zurückgreift.
So muss die eigentliche Logik nicht mehrmals entwickelt werden, sondern nur
der Aufruf der Methode muss umgelenkt werden.
Ein weiteres Problem bereitet die Übergabe von Parametern. Parameter mit
Standard-Datentypen bereiten wenig Probleme und können in einer SQLAnfrage direkt, z.B. als Literal, eingegeben werden. Es ist jedoch unklar, wie
ein komplexes Objekt als Parameter übergeben werden kann. Zum jetzigen
Zeitpunkt ist dies nicht möglich. Ob und wie dies mit SQLj-Types möglich
sein wird, ist noch unklar.
Der Einsatz von Methoden kann zudem einen gravierenden Einfluss auf die
Leistung der Datenbank haben. Statische Daten, wie sie normalerweise in
der Datenbank abgelegt werden, können indiziert werden, um den Zugriff zu
beschleunigen. Sobald Methoden an die Daten gebunden werden, wird dies
jedoch erschwert. Methoden können, abhängig von den übergebenen Parametern, sehr unterschiedliche Ergebnisse liefern. Das Ergebnis einer Methode
steht also vorher nicht fest, und lässt sich deswegen nicht indizieren. Statt
dessen muss die Methode bei einer Anfrage für jedes Objekt ausgeführt werden. Daraus resultiert eine deutlich schlechtere Leistung.
Messungen mit einer Java-Methode haben folgendes ergeben: Die Methode
hat ein ganzzahliges Attribut eines Objekts konstant um 10 erhöht. Diese Methode wurde auf einer Datenbasis von 50.000 Datensätzen ausgeführt. Dabei
enthielt das Attribut Zufallszahlen zwischen 0 und 19. In einer Select-Anfrage
wurden alle Objekte ausgewählt, die in diesem Attribut einen festen Wert von
7 enthielten. Die Anfrage dauerte 60ms. In einer zweiten Select-Anfrage wurden wiederum dieselben Objekte ausgewählt. Diesmal wurde jedoch in der
Where-Klausel nicht das Attribut direkt, sondern die Methode angewendet.
Dabei wurden alle diejenigen Objekte ausgewählt, bei denen die Methode 17
(= 7 + 10) als Ergebnis liefert. Die zweite Select-Anfrage benötigte 4930ms,
82 mal so viel wie die erste Anfrage.
Es macht keinen Sinn, alle Methoden in die Datenbank zu übernehmen. Dies
würde einen zu großen Aufwand verursachen. Nur die Methoden, die in Anfragen dringend benötigt werden, sollten in die Datenbank übernommen werden. Gerade Methoden, die ein Objekt modifizieren, sind wenig sinnvoll. Der
Umgang mit Objekten besteht meistens aus den folgenden Operationen: Laden des Objekts; modifizieren des Objekts im Arbeitsspeicher; zurückschreiben der Änderungen in die Datenbank. Beim Zurückschreiben werden die At65
tribute des Objekts mittels einer Update-Operation mit neuen Werten überschrieben. Würden modifizierende Methoden eingesetzt werden, müssten alle
Methoden sowohl im Arbeitsspeicher als auch in der Datenbank ausgeführt
werden, um alle Änderungen zu verfolgen. Dies wäre jedoch zu aufwendig
und zu langsam.
4. Wie können Vererbungsbeziehungen in der Datenbank abgebildet und genutzt werden?
Datentypen können in einer Vererbungsbeziehung zueinander stehen. Wenn
ein Attribut mit einem bestimmten Datentyp in der Datenbank definiert
wird, können darin jedoch keine Objekte eines Subtyps abgelegt werden,
wie es bei objektorientierten Programmiersprachen üblich ist. Die einzige
Möglichkeit, um auf Objekte in einer Vererbungsbeziehung polymorph zugreifen zu können, ist, diese in einer Tabellenhierarchie abzulegen. Dabei wird
für jeden konkreten Datentyp eine Tabelle erstellt. Objekte müssen immer in
die Tabelle eingefügt werden, mit dessen Typ sie exakt übereinstimmen. Dadurch, dass die Tabellen in einer Tabellenhierarchie zusammengefasst sind,
werden bei einem Zugriff auf eine Super-Tabelle ebenfalls die Objekten in
allen Sub-Tabellen zugegriffen.
Da bisher keine Möglichkeit existiert, ein Objekt als Ganzes an die Programmiersprache zu übertragen, können die Objekte jedoch nicht polymorph geladen werden. Die Typinformation geht beim Zugriff über die Super-Tabelle
verloren. Um ein Objekt mit all seinen Attributen zu laden, muss der exakte Typ des Objekts bekannt sein. Es muss ein Objekt dieses Typs in der
Programmiersprache erzeugt werden, um es manuell mit den Daten aus der
Datenbank zu füllen.
5. Wie können komplexe Objektstrukturen zwischen der Programmiersprache und der Datenbank ausgetauscht werden?
Grundsätzlich können Objekte nicht als Ganzes zwischen der Programmiersprache und der Datenbank ausgetauscht werden. Stattdessen können an der
Schnittstelle nur Attribute mit Standard-Datentypen vorkommen. Jedes Objekt muss also für die Übertragung an die Programmiersprache erst einmal in
seine einzelnen Attribute zerlegt werden. Ebenso können Objektstrukturen
nicht im Block übertragen werden. Im SQL:1999-Standard können Objekte zwar durch Referenzen miteinander verknüpft werden, die referenzierten
Objekte werden jedoch nicht automatisch geladen. Die Referenzen erleichtern lediglich den Zugriff auf die Objekte innerhalb einer Anfrage. Objektstrukturen müssen also manuell Stück für Stück aus der Datenbank geladen
werden, um sie in der Programmiersprache zu rekonstruieren. Es gibt keine
66
Unterstützung für die Übertragung komplexer Objektstrukturen.
5.1.1
Modellierungsrichtlinien
Im vorangegangenen Kapitel habe ich einige Möglichkeiten erarbeitet, wie
die objektrelationalen Konzepte zusammen mit einer objektorientierten Programmiersprache eingesetzt werden können.
Die aufgeführten Erläuterungen habe ich zu einer kleinen Menge von Richtlinien zusammengefaßt. Die folgenden Richtlinien beschreiben, wie ein Objektmodell auf ein objektrelationales Datenmodell abgebildet werden kann:
1. Zu jeder Klasse im Objektmodell wird ein entsprechender Datentyp in
der Datenbank erstellt.
2. Vererbungsbeziehungen im Objektmodell werden identisch im Datenmodell nachgebildet.
3. Die Objekte der Anwendung, auf die einzeln zugegriffen werden soll,
werden in getypten Tabellen abgelegt. Dabei wird mindestens eine Tabelle je Datentyp angelegt, mehrere, wenn die Objekte in unterschiedlichen Gruppen geordnet werden sollen.
4. Objekte in getypten Tabellen erhalten immer eine eindeutige ID. Die
Objekte werden ausschließlich über diese ID referenziert und nicht über
die Werte der Attribute. Dies gilt besonders für Fremdschlüsselbeziehungen.
5. Getypte Tabellen von Datentypen, die in einer Vererbungsbeziehung
zueinander stehen, werden in einer Tabellenhierarchie angeordnet. Nur
so ist ein polymorpher Zugriff auf die Objekte möglich.
6. 1-zu-1-Beziehungen zwischen Objekten werden durch Einbettung innerhalb einer Tabelle gespeichert.
7. n-zu-1-Beziehungen werden durch Referenzen abgebildet. Dies setzt
voraus, dass die referenzierten Objekte in einer getypten Tabelle abgelegt sind.
8. 1-zu-n-Beziehungen werden über umgekehrte Referenzen abgebildet.
Dadurch wird die Beziehung technisch in eine n-zu-1-Beziehung umgewandelt. Der Zugriff erfolgt wahlweise über die Referenzen oder durch
Join-Operationen, ebenso wie bei Fremdschlüsseln.
9. n-zu-m-Beziehungen werden durch Fremdschlüssel in einer Verknüpfungstabelle hergestellt, wie es von relationalen Datenbanken her
bekannt ist.
67
Die vorgestellte Modellierung von 1-zu-n-Beziehungen, ebenso wie die von nzu-m-Beziehungen, ist zur Zeit die einzige Möglichkeit, da bisher von den Datenbanken noch keine mengenwertigen Attribute unterstützt werden. Sobald
diese zur Verfügung stehen, können die 1-zu-n- und die n-zu-m-Beziehungen
teilweise auch durch mengenwertige Attribute mit Objekten, bzw. Referenzen
auf Objekte, modelliert werden, wie es auch schon in den objektorientierten
Programmiersprachen üblich ist.
In jedem Fall werden Verbindungen zwischen Objekten nur über die Objektidentität eines Objekts hergestellt. Dies gilt sowohl für Referenzen wie auch
für Fremdschlüssel. Es werden keine Fremdschlüssel über die Werte anderer
Attribute aufgebaut. Dadurch wird sichergestellt, dass Objekte auch dann
untereinander verknüpft bleiben, wenn sich die gespeicherten Werte ändern.
Mit diesem Vorgehen wird der Umgang mit Objektidentität und Referenzen von den objektorientierten Programmiersprachen auf die Datenbanken
übertragen.
Wie bei allen Richtlinien in der Modellierung gibt es auch hier Ausnahmen.
Die oben aufgeführten Richtlinien sind also keine starre Vorschrift, sondern
sind vielmehr ein Hinweis darauf, wie die Modellierung durchgeführt werden könnte. Im Einzelfall wird es sinnvoll sein, von den hier vorgeschlagenen
Richtlinien abzuweichen. Im Folgenden wird noch verdeutlicht werden, unter
welchen Umständen dies sinnvoll oder sogar nötig ist. Einige Einschränkungen der bestehenden Datenbanken führen dazu, dass das resultierende Datenmodell sich vom Objektmodell deutlich unterscheidet.
5.2
Beschreibung des Prototyps
Im Folgenden wird ein Prototyp beschrieben, der exemplarisch demonstriert,
wie die neuen Funktionen der objektrelationalen Datenbanken eingesetzt werden können. Für die Erstellung des Prototyps wurden die Programmiersprache Java von Sun Microsystems (Sun JDK 1.3) und die Datenbank DB2 von
IBM (Version 7.2 mit Fixpack 6) verwendet. Die Programmiersprache Java zeichnet sich durch eine gute Integration der Datenbankanbindung aus.
Die Datenbank DB2 ist in der Unterstützung des SQL:1999-Standards weit
fortgeschritten.
Die Software erlaubt es, so genannte Ressourcen-Netzwerke zu erstellen und
zu bearbeiten. Ressourcen-Netzwerke werden im Projektmanagement eingesetzt, um die zur Verfügung stehenden Ressourcen auf die anstehenden Projekte und durchzuführenden Aufgaben zu verteilen. In Abbildung 5.1 auf der
nächsten Seite ist ein einfaches Ressourcen-Netzwerk zu sehen.
68
Projekt
Titel: Diplomarbeit Personen-Tage: 200
Teil von
Aufgabe
Beschreibung: Prototyp erstellen
Personen-Tage: 40
6
Tage/Woche: 3
Ressource
Name: Malte Finsterwalder
Tage/Woche: 5
Fähigkeiten: OR-Datenbanken
Abbildung 5.1: Einfaches Ressourcen-Netzwerk
Darin wird ein Projekt Diplomarbeit“ mit einem Aufwand von 200
”
Personen-Tagen definiert. Diesem Projekt ist eine Teilaufgabe zugeordnet:
Prototyp erstellen“ mit einem Aufwand von 40 Personen-Tagen. Für die
”
Bearbeitung dieses Projektes steht die Ressource Malte Finsterwalder“ drei
”
Tage pro Woche zur Verfügung. Insgesamt steht Malte Finsterwalder fünf Tage pro Woche zur Verfügung, er kann also noch zwei Tage pro Woche andere
Aufgaben übernehmen. Zudem besitzt er Kenntnisse über objektrelationale
Datenbanken.
Solche Ressourcen-Netzwerke werden im Projektmanagement eingesetzt, um
Abhängigkeiten zwischen Projekten, Teilaufgaben und den Bearbeitern dieser
Aufgaben herzustellen und zu untersuchen. Insbesondere Änderungen der
Verfügbarkeit können durchgespielt und die resultierende Gesamtlaufzeit der
Projekte kann ermittelt werden.
Die Analyse von Ressourcen-Netzwerken ist für die vorliegende Arbeit jedoch weniger von Interesse. Hier interessieren vor allem die Speicherung der
Datenstrukturen und der Zugriff auf gespeicherte Netzwerke. Die RessourcenNetzwerke wurden gewählt, da sie ein komplex strukturiertes Material sind
und alle gängigen Objektebeziehungen darin enthalten sind.
Die hier vorgestellte Software ist für den exklusiven Zugriff ausgelegt. Das
bedeutet, dass ein Ressourcen Netzwerk zu jeder Zeit nur von einem Arbeitsplatz aus bearbeitet wird. Probleme, die durch den gleichzeitigen Zugriff auf
dasselbe Netzwerk auftreten können, werden hier nicht weiter behandelt, da
dies den Rahmen des Prototyps sprengen würde.
69
Werkzeug
Grafischer Editor
?
Material
Ressourcen-Netzwerk
6
?
Fachlicher Service
Figure-Service
Abbildung 5.2: Grobe Struktur der Software
Die grobe Struktur der Anwendung ist in Abbildung 5.2 zu sehen. Dabei
wird die typische WAM-Aufteilung deutlich. Das zu bearbeitende Material ist
das Ressource Netzwerk. Um dieses zu bearbeiten, steht ein grafischer Editor
bereit. Um die Netzwerke dauerhaft zu speichern und zu verwalten, wurde ein
fachlicher Service (Figure-Service) erstellt, der vom Editor verwendet wird.
Der Service und der Editor tauschen Materialien als Ganzes miteinander aus,
da im Editor immer das gesamte Ressourcen-Netzwerk dargestellt wird.
Ein Ressourcen-Netzwerk ist ein relativ komplex verknüpftes Material. In
Abbildung 5.3 auf der nächsten Seite ist ein vereinfachtes Klassen-Diagramm
eines Ressourcen-Netzwerks abgebildet. Das Resource Netzwerk als Ganzes
wird durch eine Figur (Figure) repräsentiert. Sie verweist auf alle Elemente
des Netzwerks, wovon es beliebig viele geben kann. Es gibt zwei Sorten von
Elementen: Knoten (FigureElement) und Verbindungen (FigureConnector),
die unter dem abstrakten Datentyp BaseElement“ zusammengefasst werden.
”
Knoten sind Elemente wie Projekt, Aufgabe und Ressource. Für jedes Element wird ein konkreter Subtyp erstellt, was in der Grafik nicht dargestellt
wird.
Die Knoten werden durch Verbindungen miteinander verknüpft. Auch hiervon existieren zwei verschieden Subtypen: Verbindungen zwischen Tasks und
Projekten sowie Verbindungen zwischen Ressourcen und Projekten bzw.
Tasks. Die eigentliche Verbindung wird dadurch hergestellt, dass der Startpunkt einer Verbindung einen Verbindungspunkt (ConnectionPoint) eines
70
Figure
*-
1-
BaseElement
J
J
*-
Form
FormField
J
J
FigureElement
FigureConnector
start
end
*-
2-
ConnectionPoint
ConnectionPoint
Abbildung 5.3: Klassen-Diagramm für ein Ressourcen-Netzwerk
Knotens referenziert und der Endpunkt der Verbindung einen Verbindungspunkt eines anderen Knotens referenziert. In dem Beispiel in Abbildung 5.1
auf Seite 69 existiert beispielsweise eine Verbindung zwischen der Aufgabe
und dem Projekt. Der Startpunkt der Verbindung referenziert den Verbindungspunkt des Aufgaben-Elements, der Endpunkt der Verbindung den des
Projekt-Elements.
Die Informationen, die zu einem Element oder einer Verbindung gespeichert
werden sollen, werden in einem angehängten Formular erfasst. Dazu wird
das bestehende Formularwesen des JWAM-Frameworks verwendet. Ein Formular besteht aus einer Menge von Formularfeldern. Zur Bearbeitung von
Formularen stellt das Framework bereits Werkzeuge zur Verfügung.
Bisher wurde die Objektstruktur eines Ressourcen-Netzwerks dargestellt. Im
Folgenden wird gezeigt, wie eine entsprechende Datenstruktur erstellt werden
kann und wie diese aussieht. Dabei kommen die im Kapitel 5.1.1 auf Seite 67
aufgestellten Modellierungsrichtlinien zum Einsatz.
Entsprechend der 1. Richtlinie wird zu jeder Klasse im Objektmodell ein
entsprechender Datentyp in der Datenbank erstellt. Dies ist jedoch nicht für
alle Datentypen machbar.
Die beiden Typen BaseElement“ und FigureElement“ unterschieden sich
”
”
nur dadurch voneinander, dass bei letzterem eine Liste mit Connection”
Points“ hinzugefügt wurde. Damit wird zwischen einem FigureElement“ und
”
seinen ConnectionPoints“ eine 1-zu-n-Beziehung aufgebaut. Diese Referenz”
Beziehung wird, nach Richtlinie 8, im Datenbankmodell jedoch durch eine
umgekehrte Referenz vom ConnectionPoint“ zum FigureElement“ model”
”
liert. Die Liste mit ConnectionPoints“ entfällt also beim FigureElement“”
”
71
Datentyp in der Datenbank. Da dies das einzige Unterscheidungsmerkmal
zum Datentyp BaseElement“ war, unterscheiden sich die beiden Datenty”
pen FigureElement“ und BaseElement“in der Datenbank nicht mehr von
”
”
einander.
Nun wäre es denkbar, die beiden Typen trotzdem einzuführen, um die strukturelle Ähnlichkeit der Modellierung auszunutzen. Dies geht jedoch aufgrund
einer Einschränkung der verwendeten Datenbank nicht. Es ist nicht möglich,
eine Tabellenhierarchie mit zwei getypten Tabellen anzulegen, bei denen sich
die Datentypen in keinem Attribut unterscheiden. Eine eigene Tabelle kann
nur dann angelegt werden, wenn der Subtyp mindestens ein Attribut zum
Datentyp hinzufügt. Aus diesem Grund entfällt im Datenmodell der Typ
BaseElement“ und an seine Stelle tritt der Typ FigureElement“. Das ver”
”
einfacht das Datenmodell in diesem Fall sogar etwas.
Die Beziehungen zwischen den Datentypen sind gemäß der Richtlinien
aufgebaut. Zwischen Figure t“ und FigureElement t“ besteht eine 1-zu”
”
n-Beziehung, die durch eine umgekehrte Referenz vom FigureElement“
”
zur Figure“ abgebildet wird. Gleiches gilt für die Beziehung zwischen
”
FigureElement t“ und FormField t“, sowie zwischen FigureElement t“
”
”
”
und ConnectionPoint t“. Zwischen FigureConnector t“ und Connection”
”
”
Point t“ bestehen zwei n-zu-1-Beziehungen, die jeweils durch eine Referenz
abgebildet werden.
Der Datentyp Form“ wird lediglich dazu verwendet, eine Menge von Form”
”
Fields“ zu bündeln und als eine Einheit zu kapseln. Eine solche Modellierung
ist jedoch in der Datenbank überflüssig, da die Datenbank problemlos mit
Mengen operieren kann. Es wird daher in der Datenbank kein Form“ abge”
legt, sondern lediglich die FormFields“.
”
Das entstandene Datenbankmodell ist in der Abbildung 5.4 auf der nächsten
Seite zu sehen.
Eine Ähnlichkeit der Modelle ist offensichtlich, wenn sich auch aufgrund der
technischen Einschränkungen leichte Unterschiede ergeben. Insbesondere die
Abbildung der Vererbungsbeziehung, die in relationalen Datenbanken Probleme bereitet, macht bei objektrelationalen Datenbanken weniger Schwierigkeiten.
Zu jedem der im Diagramm aufgeführten Typen wird jeweils eine getypte
Tabelle erstellt. Daraus ergeben sich fünf Tabellen: Eine für Figuren, eine für
FigureElements“, eine für FigureConnectors“, eine für ConnectionPoints“
”
”
”
und eine für FormFields“.
”
Die Tabelle FigureConnectors“ ist zudem eine Sub-Tabelle von der Figu”
”
reElements“-Tabelle. Dadurch ist es möglich, alle Elemente einer Figur mit
72
Figure t * FigureElement t J
J
*
FormField t
@
I
@
@
@
@
@*
@ ConnectionPoint t
FigureConnector t start
end
2-
ConnectionPoint t
Abbildung 5.4: Datenbank-Diagramm für ein Ressourcen-Netzwerk
einer einzigen Anfrage zu laden. Außerdem ist es so möglich, dass im Typ
FormField t“ eine Referenz auf ein Objekt vom Typ FigureElement t“ de”
”
finiert wird, die dann polymorph ebenso auf einen FigureConnector“ verwei”
sen kann. Davon wird Gebrauch gemacht, um auch am FigureConnector“
”
zusätzliche Informationen zu speichern. So wird beispielsweise an einer Verbindung zwischen Ressourcen und Projekten die Zeit angegeben, die diese
Ressource für die Bearbeitung dieses Projektes zur Verfügung steht.
In Abbildung 5.3 auf Seite 71 wurde ein vereinfachtes Klassen-Diagramm für
das Material Ressourcen Netzwerk dargestellt. Vereinfacht deswegen, weil
weder die Attribute der Klassen, noch ihre Methoden dargestellt wurden.
Methoden können in die Datenbank zwar grundsätzlich übertragen werden,
dies macht jedoch nur für diejenigen Methoden Sinn, die auch in DatenbankAnfrage eingesetzt werden sollen. Für die vorliegenden Klassen ist dies jedoch
nicht der Fall.
Zusätzlich zu den gezeigten Klassen und ihren Beziehungen verwenden einige
der Klassen den Typ Point“, um einen graphischen Punkt mit X- und Y”
Koordinaten darzustellen. Beispielsweise wird die Position eines Knotens in
einem Attribut vom Typ Point“ gespeichert. Ebenso wird die Position eines
”
ConnectionPoints“ auf diese Weise gespeichert.
”
In der Abbildung 5.5 auf der nächsten Seite sind einige Klassen mit ihren
für die Speicherung relevanten Attributen aufgeführt. Die meisten Klassen
haben noch weitere Attribute, die jedoch nicht persistent gespeichert werden
und deswegen hier vernachlässigt werden können.
73
public class Point {
private int x;
private int y;
...
}
public class ConnectionPoint {
private String dbId;
private Point position;
...
}
public class FigureElement extends BaseElement {
private String dbId;
private Point position;
private List connectionPoints;
...
}
public class FigureConnector extends BaseElement {
private Point startPoint;
private Point endPoint;
private ConnectionPoint startConnectionPoint;
private ConnectionPoint endConnectionPoint;
...
}
Abbildung 5.5: Für die Speicherung relevante Attribute einiger Java Klassen
In der Datenbank wurde für jede dieser Klassen ein entsprechender Datentyp erstellt. Die resultierenden Datentypen sind in Abbildung 5.6 auf der
nächsten Seite zu sehen. Die Ähnlichkeit dieser Datentypen mit den Klassendefinitionen der Programmiersprache ist offensichtlich. Zu jedem Attribut der
Java Klasse, das persistent gespeichert werden soll, wurde ein entsprechendes Attribut im Datentyp der Datenbank erstellt. Die Attribute der Java
Klassen, die nicht gespeichert werden sollen, werden vernachlässigt.
Der Zugriff auf die Daten erfolgt über SQL-Abfragen. Die Abfragen liefern
Ergebnis-Tabellen, die nur Attribute mit Standard-Datentypen enthalten.
Das bedeutet, dass bei der Anfrage die Attribute einzeln verarbeiten werden
müssen. Die Objekte können nicht als Ganzes übertragen werden.
74
CREATE TYPE Point t AS
( x INT,
y INT )
CREATE TYPE ConnectionPoint t AS
( position Point t,
figureElement REF(FigureElement t) )
CREATE TYPE FigureElement t AS
( type VARCHAR(100),
name VARCHAR(100),
position Point t,
figure REF(Figure t) )
CREATE TYPE FigureConnector t UNDER FigureElement t AS
( startPoint Point t,
endPoint Point t,
startCP REF(ConnectionPoint t),
endCP REF(ConnectionPoint t) )
Abbildung 5.6: Datentypen in der Datenbank
In der Select-Anweisung müssen alle Attribute des Datentyps aufgeführt werden. Die komplexen, eingebetteten Objekte, wie startPoint und endPoint vom
Typ Point t“, müssen ebenfalls in ihre Einzelteile zerlegt werden, in diesem
”
Fall die beiden Attribute für die X- und die Y-Koordinate.
In Abbildung 5.7 ist eine Anfrage zu sehen, die alle FigureConnector“ einer
”
bestimmten Figure“ lädt.
”
select oid, type, name,
startPoint..x, startPoint..y,
endPoint..x, endPoint..y,
startCP, endCP
from FigureConnectors
where figure–>name = ’Diplomarbeit’
Abbildung 5.7: Laden aller FigureConnector“ der Figur Diplomarbeit“
”
”
Die beiden Attribute startCP und endCP, die eine Referenz auf einen
ConnectionPoint“ enthalten, werden direkt in der Select-Anweisung auf”
geführt. Damit wird die Objektidentität des zugeordneten Connection”
75
Points“ geladen und nicht der ConnectionPoint“ selbst. Diese ID wird im
”
Programm dazu verwendet, den bereits geladenen ConnectionPoint“ mit
”
dieser ID aufzufinden.
Im where“-Teil der Anweisung wird spezifiziert, dass nur die FigureConnec”
”
tor“ der Figur mit Namen Diplomarbeit“ geladen werden. Hierfür wird die
”
Referenz auf die zugehörige Figur verwendet.
Für jede Zeile der Ergebnis-Tabelle wird in der Anwendung ein Figure”
Connector“-Objekt erstellt und mit den gelesenen Daten gefüllt. Das Vorgehen ist identisch mit dem bei relationalen Datenbanken. Die erzeugten
Objekte werden dann in die Liste von FigureElements“ der Figure eingetra”
gen.
Wir haben bereits gesehen, dass es drei verschiedene FigureElements“ und
”
zwei verschiedene FigureConnector“ gibt. Es gibt die FigureElements“:
”
”
Projekt“, Aufgabe“ und Ressource“. Es gibt dazu einen FigureConnec”
”
”
”
tor“ zwischen Resourcen und Projekten oder Aufgaben und einen zwischen
Aufgaben und Projekten. Die verschiedenen FigureElements“ unterschei”
den sich jedoch nur durch ihre angehängten Formulare und durch den Programmcode der Klasse. Die Attribute und die Struktur der Elemente selbst
sind identisch. Die Datentypen in der Datenbank würden sich deswegen nicht
voneinander unterscheiden. Daher wurden die unterschiedlichen Datentypen
nicht in der Datenbank definiert.
Dadurch wird das Datenmodell zwar vereinfacht, die Zuordnung von Datentypen der Programmiersprache zu Datentypen der Datenbank wird jedoch
etwas erschwert. Es werden mehrere Datentypen der Programmiersprache
auf den selben Datentyp in der Datenbank abgebildet. Der ursprüngliche
Datentyp eines Objekts der Programmiersprache geht in der Datenbank also
verloren. Um dennoch eine Wiederherstellung der Objekte zu ermöglichen,
wurde in der Beispielanwendung zu jedem Objekt der Name der konkreten
Klasse abgelegt. Diese Information wird beim Laden des Objekts dazu verwendet, ein Objekt der richtigen Klasse zu instantiieren.
Das Speichern von Daten in der Datenbank geschieht, ebenso wie bisher,
mit Insert- und Update-Anweisungen. Beim Einfügen in eine getypte Tabelle muss zudem immer eine eindeutige Objektidentität angegeben werden.
Beim Speichern von Referenzen muss die korrekte Objektidentität desjenigen
Objekts eingetragen werden, das referenziert werden soll. In dem Prototyp
wurde dieser Vorgang dadurch erleichtert, dass alle Objekte ihre DatenbankOID zur Laufzeit in einem Attribut vorhalten. Dadurch kann diese OID bei
einem Insert- oder Update-Befehl direkt verwendet werden, ohne sie erneut
76
aus der Datenbank zu laden. Die Objektidentität der Datenbank hält damit
Einzug in das Objektmodell der Anwendung. Diese Technik wird auch bei
relationalen Datenbanken bereits eingesetzt und ist ein gutes Mittel, um eine
Abbildung von den Objekten im Speichern auf die zugehörigen Daten in der
Datenbank herzustellen (vgl. [Fowler 02]).
In Abbildung 5.8 ist der Insert-Befehl zu sehen, der ein FigureElement“ in
”
die Datenbank einfügt.
insert into FigureElements
( OId, type, name, position, figure ) values
( FigureElement t(?), ?, ?, Point t()..x(?)..y(?), Figure t(?) )
Abbildung 5.8: Speichern eines FigureElement“
”
Die Fragezeichen in dem SQL-Befehl bezeichnen Platzhalter, die vor dem eigentlichen Einfügen mit Werten gesetzt werden. Die verschiedenen Attribute
müssen dabei alle einzeln gesetzt werden. Die OID des FigureElements“,
”
ebenso wie die der zugehörigen Figure, müssen ebenfalls manuell gesetzt
werden. Es gibt keine automatische Verknüpfung zwischen den Objekten im
Arbeitsspeicher der Anwendung und den Objekten in der Datenbank. Auch
bei einem Update-Befehl muss das korrekte Objekt anhand der OID explizit
identifiziert werden.
5.3
Auswertung
Bei der praktischen Anwendung der Datenbanken wird deutlich, dass die
Modelle zwischen Programmiersprache und Datenbank nach wie vor nicht
gut aufeinander abgestimmt sind.
Die objektrelationalen Datenbanken erlauben eine Datenmodellierung, die
der objektorientierten Software ähnlicher ist, wodurch sich das Datenmodell
weniger vom Objektmodell der Software unterscheidet als bei rein relationalen Datenbanken. Es müssen jedoch weiterhin zwei unterschiedliche Modelle
erstellt, gepflegt und auf einander abgebildet werden. Dies ist nach wie vor
mit erheblichem Aufwand verbunden. Insgesamt ist keine wesentliche Arbeitserleichterung erkennbar.
Die in der Auswertung des SQL:1999-Standards in Kapitel 4.4 auf Seite 57
aufgezeigten Schwierigkeiten haben sich in der Implementation entsprechend
manifestiert.
In der Datenbank müssen die entsprechenden Datentypen manuelle erstellt
werden. Dadurch, dass keine komplexen Objekte als Ganzes ausgetauscht
77
werden können, müssen die Objekte beim Zugriff zerlegt und in der Anwendung manuell wieder rekonstruiert werden. Eine Erleichterung im Vergleich
zu den relationalen Datenbanken ist hier nicht gegeben.
Die Objektidentitäten in der Datenbank müssen manuell verwaltet werden.
Um eine Abbildung zwischen den Objekten im Speicher und denen der Datenbank herzustellen, wurde die Objektidentität in einem Attribut des Objekts aufgenommen. Dies muss jedoch manuell programmiert und verwaltet
werden.
In der Datenbank können Referenzen aufgrund der vorhandenen Einschränkungen nur für einen Teil der Verknüpfungen angewendet werden. 1zu-n- und n-zu-m-Beziehungen können nicht ohne weiteres mit Referenzen
abgebildet werden.
Untereinander verknüpfte Objekte müssen einzeln in die Anwendung geladen
und dort erneut verknüpft werden. Wenn Objekte in der Datenbank mehrfach
referenziert werden, wie es bei den ConnectionPoints“ der Fall ist, muss
”
zudem sichergestellt werden, dass Objekte nicht mehrfach geladen werden,
sondern bereits geladene Objekte miteinander verknüpft werden. Um dies
zu gewährleisten, muss ein Objekt-Cache eingeführt werden. Nur wenn ein
Objekt noch nicht im Cache liegt, wird es tatsächlich aus der Datenbank
geladen. Ansonsten wird das bereits geladene Objekt verknüpft. Auch dies
muss manuell programmiert und verwaltet werden.
Die fehlende Typinformation beim Zugriff auf Tabellenhierarchien wurde im
Prototypen dadurch kompensiert, dass der Name des konkreten Typs zusätzlich in der Tabelle gespeichert wird. Aufgrund des Namens kann dann manuell ein Objekt dieses Typs erzeugt werden. Das führt jedoch dazu, dass alle
konkreten Typen bekannt sein müssen. Das Hinzufügen eines Typs muss entsprechend eingepflegt werden. Dies wollte der objektorientierte Ansatz mit
Hilfe von Vererbung und Polymorphie gerade verhindern.
Darüber hinaus existieren noch einige technische Einschränkungen bei den
Tabellenhierarchien. So müssen sich die Datentypen der Tabellen in mindestens einem Attribut unterscheiden. Da manche Datentypen diesem Kriterium nicht genügen, werden Objekte unterschiedlichen Typs in derselben
Tabelle abgelegt.
78
Kapitel 6
Schlussfolgerungen und
Ausblick
Die größten Schwierigkeiten beim Einsatz von Datenbanken entstehen dadurch, dass zwei unterschiedliche Modelle aufeinander treffen.
In Kapitel 3.3 auf Seite 30 wurde aufgezeigt, dass zwischen dem objektorientierten Modell der Programmiersprachen und dem relationalen Modell
einige grundlegende Differenzen bestehen. Das objektorientierte Modell der
Programmiersprachen ist imperativ und auf die Modellierung von Verhalten
ausgelegt. Das relationale Modell ist hingegen deskriptiv und auf die Modellierung von Daten und Fakten ausgerichtet. Die Kombination dieser beiden
Modelle bereitet einige Schwierigkeiten, was sich in einem hohen Entwicklungsaufwand bei der Erstellung von Softwareanwendungen niederschlägt.
Damit die beiden Modelle besser miteinander kombinieren werden können
und damit die Vorteile des objektorientierten Modells auch in relationalen
Datenbanken genutzt werden können, wurde das objektrelationale Modell
entwickelt.
Das objektrelationale Modell von Date und Darwen ist darauf ausgerichtet,
die Vorteile der Objektorientierung für die Modellierung in relationalen Datenbanken nutzbar zu machen. Das Modell hat hingegen nicht das primäre
Ziel, eine enge Integration mit den objektorientierten Programmiersprachen
zu ermöglichen, um dadurch die Kombination der beiden Techniken zu erleichtern. Das zeigt sich auch daran, dass die Integration in objektorientierte
Programmiersprachen nicht weiter betrachtet wird.
Daher bleiben einige konzeptionelle Unterschiede zwischen dem objektorientierten und dem objektrelationalen Modell bestehen. Insbesondere der Umgang mit Vererbung und mit Objektidentität unterscheidet sich wesentlich
bei den beiden Modellen (siehe Kapitel 3.4.2 auf Seite 39).
79
Im objektorientierten Modell bekommt jedes Objekt bei seiner Erzeugung
einen festen Typ zugeteilt, den es nicht wieder verändern kann. Zudem erhält
jedes Objekt eine eindeutige Objektidentität.
Im objektrelationalen Modell können Objekte zur Laufzeit ihren Typ
verändern. Objekte nehmen automatisch den am besten passenden Typ an.
Zudem werden Objekte nur anhand ihres Zustandes identifiziert. Eine Objektidentität gibt es in dem Modell nicht.
Wie dieses unterschiedliche Verhalten bei einem gemeinsamen Einsatz in Einklang gebracht werden kann, wird leider nicht erläutert.
Das objektrelationale Modell von Date und Darwen stellt ein in sich schlüssiges und formal gut begründetes Modell dar. Die praktische Relevanz ist jedoch eingeschränkt. Bisher existiert keine Implementierung des Modells und
es ist nicht absehbar, ob bestehende Datenbanken das Modell jemals umsetzen werden. Das Modell entspricht, ähnlich dem relationalen Modell, einer
Leitlinie. Die praktischen Umsetzungen entscheiden sich mehr oder weniger
Stark von dieser Leitlinie.
Eine wesentlich höhere praktische Relevanz besitzt der SQL-Standard. Der
SQL-Standard, der von praktisch allen relationalen Datenbanken unterstützt
wird, wurde im neuen SQL:1999-Standard um objektorientierte Konzepte erweitert. Die festgelegten Erweiterungen unterscheiden sich jedoch in einigen
Punkten vom objektrelationalen Modell, wie es von Date und Darwen vorgeschlagen wird. Anstelle eines theoretisch fundierten Modells steht hier die
praktische Umsetzbarkeit im Vordergrund. Zudem sollen die Erweiterungen
mit dem bestehenden SQL-Standard konform sein. Eine formale Grundlage
fehlt dem SQL-Standard. In einigen Punkten wird eine stärkere Annäherung
an das objektorientierte Modell versucht, als es beim objektrelationalen Modell von Date und Darwen der Fall ist. Einige objektorientierte Konzepte
werden jedoch mangelhaft und inkonsistent umgesetzt (siehe Kapitel 4.4 auf
Seite 57).
Eine wesentlicher Mangel des SQL:1999-Standards ist zudem die fehlende Integration mit den objektorientierten Programmiersprachen. Der Zugriff auf
die Datenbanken findet ausschließlich über ein Call Level Interface (CLI)
statt. Insbesondere gehen sämtliche Typinformationen von benutzerdefinierten Datentypen an dieser Schnittstelle zur Datenbank verloren. Die Kommunikation zwischen der Programmiersprache und der Datenbank wird dadurch
auf einfache relationale Strukturen reduziert. Dadurch wird der Austausch
von Objekten, ebenso wie ein effektiver Einsatz von Vererbung und Polymorphismus verhindert.
80
Die objektorientierten Erweiterungen kommen nur intern in der Datenbank
zum Tragen. Die Anbindung an die objektorientierten Programmiersprachen hat sich im Vergleich zu den relationalen Datenbanken hingegen nicht
geändert. Dies schlägt sich auch durch einen unvermindert hohen Aufwand
beim praktischen Einsatz der objektrelationalen Datenbanken nieder. Zudem
bestehen in der hier verwendeten Datenbank DB2 noch einige technische
Mängel bei der Umsetzung der Konzepte.
Auch beim Einsatz objektrelationaler Datenbanken in Verbindung mit objektorientierten Programmiersprachen müssen weiterhin zwei unterschiedliche Modelle miteinander interagieren. Die beiden Modelle haben sich im Vergleich zu den relationalen Datenbanken zwar etwas angenähert, eine vernünftige Integration der beiden Modelle findet jedoch nicht statt. Die schlechte
Schnittstelle zwischen den beiden Technologien stellt ein wesentliches, wenn
nicht sogar das eigentliche Problem dar. Gerade an der Schnittstelle hat sich
jedoch wenig geändert. Dadurch, dass weiterhin nur einfache Relationen mit
ausschließlich Standard-Datentypen zwischen der Datenbank und den Programmiersprachen ausgetauscht werden können, bleibt der Aufwand für den
gemeinsamen Einsatz der beiden Technologien unverändert hoch.
Es ist unwahrscheinlich, dass der dritte Teil des SQLj-Standard ( SQLj”
Types“) eine wesentliche Verbesserung für die Zusammenarbeit der beiden
Technologien bringen wird. Die konzeptionellen Schwächen der Datenbanken
können dadurch nicht korrigiert werden. Der Austausch komplexer Objekte wird zwar erleichtert, der Einsatz von Polymorphie ist jedoch weiterhin
nur mittels komplizierter Tabellenhierarchien möglich. Objektidentität und
Referenzen zwischen Objekten müssen weiterhin manuell koordiniert werden.
Eine vernünftige Integration der beiden Technologien erfordert meiner Meinung nach eine Annäherung von beiden Seiten. Die Konzepte sollten dabei
so eingeführt werden, dass eine problemlose Kooperation der beiden Technologien ermöglicht wird. Dies ist auf zwei Arten zu erreichen: Entweder
werden die Konzepte so gut aneinander angepasst, dass in beiden Technologien dieselben Konzepte umgesetzt sind, oder es werden klare Prinzipien
erarbeitet, wie unterschiedliche Konzepte gemeinsam genutzt und aufeinander abgebildet werden können. Beides findet momentan nicht statt. Die Datenbanken integrieren objektorientierte Konzepte nur unzureichend. Darüber
hinaus wurde die Kooperation mit den objektorientierten Programmiersprachen vernachlässigt. Wenn die objektrelationalen Datenbanken eine Erleichterung bei der Erstellung objektorientierter Software bringen sollen, besteht
hier ein wesentlicher Nachholbedarf.
Neben einer besseren Integration der objektorientierten Konzepte in die rela81
tionalen Datenbanken muss jedoch auch umgekehrt eine bessere Integration
der objektrelationalen Konzepte in die objektorientierten Programmiersprachen stattfinden. Mögliche Ansätze dazu wurden im Kapitel 3.3.2 auf Seite 35
erläutert.
Es muss jedoch auch die Frage gestellt werden, ob die Kombination von relationalen und objektorientierten Konzepten überhaupt der richtige Ansatz
für eine persistente Datenhaltung ist: Die Erfahrung der letzten Jahre hat
gezeigt, dass wesentliche Schwierigkeiten mit der Kombination dieser unterschiedlichen Konzepte verbunden sind. Welche Vorteile des relationalen
Modells sind diesen Aufwand wert? Kann ein vergleichbarer Nutzen auch
mit anderen Systemen erreicht werden? Stellt vielleicht ein rein objektorientiertes System letztendlich eine bessere Alternative dar, da bei einer solchen
Lösung keine konzeptionellen Unterschiede überbrückt werden müssen? Ist
ein einheitliches Modell trotz der unterschiedlichen Anforderungen an Datenbanken auf der einen Seite und Programmiersprachen auf der anderen Seite
überhaupt möglich?
Der aktuelle Entwicklungsstand der persistenten Datenhaltung lässt nach wie
vor viel Raum für Verbesserungen erkennen. Die Einführung objektrelationaler Datenbanken hat daran wenig geändert.
82
Abbildungsverzeichnis
2.1
2.2
2.3
3-Schichten Architektur . . . . . . . . . . . . . . . . . . . . . . 5
Architektur einer WAM-Anwendung . . . . . . . . . . . . . . 8
EJB 3-Schichten Architektur . . . . . . . . . . . . . . . . . . . 18
3.1
3.2
Eine Relation mit vier Attributen in Tabellenform dargestellt. 27
Fremdschlüsselbeziehung zwischen zwei Relationen . . . . . . . 28
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
4.10
4.11
4.12
4.13
4.14
4.15
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
SQL-Beispiel:
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
Erzeugen eines strukturierten Datentyps . . . .
Erzeugen einer Tabelle . . . . . . . . . . . . . .
Abfragen einer Tabelle mit Adress t“-Attribut
”
Erzeugen einer getypten Tabelle . . . . . . . . .
Erzeugen einer Tabelle mit Referenz-Attribut .
Festlegen des scopes“ einer Referenz . . . . . .
”
Abfragen einer Tabelle mit Referenz-Attribut . .
Einfügen eines Eintrags in Tabelle Person“ . .
”
Ändern eines Eintrags in der Tabelle Person“ .
”
Einfügen eines Eintrags in Adressen“ . . . . . .
”
Einfügen eines Eintrags in Tabelle Person2“ . .
”
Einfügen zweier Einträge mit bekannter OID . .
Erzeugen eines Subtyps . . . . . . . . . . . . . .
Erzeugen einer Sub-Tabelle . . . . . . . . . . . .
verwenden des Mengen-Konstruktors Array“ .
”
Einfaches Ressourcen-Netzwerk . . . . . . . . . . . . . . . . .
Grobe Struktur der Software . . . . . . . . . . . . . . . . . . .
Klassen-Diagramm für ein Ressourcen-Netzwerk . . . . . . . .
Datenbank-Diagramm für ein Ressourcen-Netzwerk . . . . . .
Für die Speicherung relevante Attribute einiger Java Klassen .
Datentypen in der Datenbank . . . . . . . . . . . . . . . . . .
Laden aller FigureConnector“ der Figur Diplomarbeit“ . . .
”
”
Speichern eines FigureElement“ . . . . . . . . . . . . . . . .
”
83
46
46
47
47
48
49
49
50
50
52
52
53
54
54
56
69
70
71
73
74
75
75
77
84
Tabellenverzeichnis
3.1
3.2
3.3
Eigenschaften des objektorientierten Modells . . . . . . . . . . 25
Relationales Modell im Vergleich zum OO-Modell . . . . . . . 33
Eigenschaften der Modelle im Vergleich . . . . . . . . . . . . . 40
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
4.10
Tabelle Person“ mit einem Attribut vom Typ Adress t“
”
”
Abfrageergebnis von Tabelle Person“ . . . . . . . . . . .
”
Tabelle Adressen“ vom Typ Adress t“ . . . . . . . . .
”
”
Tabelle Person2“ mit Referenz-Attribut . . . . . . . . .
”
Abfrageergebnis von Tabelle Person2“ . . . . . . . . . .
”
Tabelle Person“ mit zusätzlichem Eintrag . . . . . . . .
”
Tabelle Person“ mit geändertem Eintrag . . . . . . . . .
”
Tabelle PlzAdressen“ vom Typ PlzAdress t“ . . . . . .
”
”
Ergebnis des Befehls: Select * from Adressen“ . . . . . .
”
Objektrelationales Modell im Vergleich zu SQL:1999 . . .
85
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
46
47
48
48
49
50
51
55
55
61
86
Literaturverzeichnis
[Ambler 00] Scott W. Ambler. Mapping objects to relational databases –
What you need to know and why. July 2000.
URL: http://www-4.ibm.com/software/developer/library/
mapping-to-rdb/index.html (Okt 2002)
[Ambler 00b] Scott W. Ambler. Mapping Objects To Relational Databases.
October 2000.
URL: http://www.AmbySoft.com/mappingObjects.pdf (Okt 2002)
[Brown et al. 96] Kyle Brown, Bruce G. Whitenack Crossing Chasms: A Pattern Language for Object-RDBMS Integration. — veröffentlicht in:
[Vlissides et al. 96], S. 227-238
[Codd 70] E. F. Codd. A Relational Model of Data for Large Shared Data
Banks Communications of the ACM / Volume 13 / Number 6 / June,
1970
[Codd 90] E. F. Codd. The Relational Model for Database Management: Version 2. Addison-Wessley, 1990
[Coldewey, Keller 96] Jens Coldewey, Wolfgang Keller. Objektorientierte Datenintegration – ein Migrationsweg zur Objekttechnologie. OBJEKTspektrum Juli/August 1996, Nr. 4, S. 20-28.
[Database Advisor] Slowed DBMS Market Means Tight Competition. Database Advisor, 29 Mai 2001.
URL: http://advisor.com/Articles.nsf/aid/SMITT247 (Okt 2002)
[Date 00] C. J. Date. An Introduction to Database Systems. Seventh Edition,
Addison-Wesley, 2000
[Date, Darwen 00] C. J. Date, Hugh Darwen. Foundation for Future Database Systems – The Third Manifesto. Second Edition, Addison-Wesley,
2000
87
[Fowler 99] Martin Fowler. Refactoring. Addison-Wesley, 1999.
[Fowler 02] Martin Fowler. Patterns of Enterprise Application Architecture .
URL: http://www.martinfowler.com/isa/index.html (Okt 2002)
[Gamma et al. 95] Erich Gamma, Gichard Helm, Ralph Johnson, John Vlissides Design Patterns. Addison-Wesley, 1995
[Heuer 97] Andreas Heuer. Objektorientierte Datenbanken. 2. Auflage,
Addison-Wesley, 1997.
[JWAM] JWAM-Framework
URL: http://www.jwam.de (Okt 2002)
[Keller, Coldewey 97] Wolfgang Keller, Jens Coldewey. Accessing Relational
Databases — veröffentlicht in: [Martin et al. 98], S. 313-343
[Keller 98] Wolfgang Keller. Object/Relational Access Layers – A Roadmap,
Missing Links and More Patterns. EuroPLoP 1998.
URL: http://www.objectarchitects.de/ObjectArchitects/papers/
Published/ZippedPapers/or06 proceedings.pdf (Okt 2002)
[Martin et al. 98] Robert Martin, Dirk Riehle, Frank Buschmann (eds.). Pattern Languages of Program Design 3. Addison-Wesley, 1998.
[McClure 97] Steve McClure. Object Database vs. Object-Relational Databases. IDC Bulletin #14821E, 1997
URL: http://www.cai.com/products/jasmine/analyst/idc/14821Eat.htm
(Okt 2002)
[Meyer 97] Bertrand Meyer. Object-Oriented Software Construction. Second
Edition, Prentice-Hall, 1997
[ODMG] Object Data Management Group
URL: http://www.odmg.org (Okt 2002)
[Otto, Schuler 2000] Michael Otto, Norbert Schuler Fachliche Services: Geschäftslogik als Dienstleistung für verschiedene
Benutzungsschnittstellen-Typen. Diplomarbeit der Universtität
Hamburg, Fachbereich Informatik, 2000
[Stonebraker, Brown 99] Michael Stonebraker, Paul Brown. ObjectRelational DBMSs, 2nd ed. Morgan Kaufmann Publishers Inc.,
1999.
88
[TPC] Transaction Processing Performance Council
URL: http://www.tpc.org (Okt 2002)
[Vlissides et al. 96] John Vlissides, James Coplien, Norman Kerth (eds.).
Pattern Languages of Program Design 2. Addison-Wesley, 1996.
[Wegner 90] Peter Wegner. Concepts and Paradigms Of Object-Oriented Programming. OOPS Messenger, Vol. 1, August 1990, S. 8-87
[Zhang, Ritter 01] Weiping Zhang, Norbert Ritter. Leistungsuntersuchung
von ORDB-gestützten objektorientierten Anwendungssystemen. Tagungsband der GI-Fachtagung Datenbanksysteme in Büro, Technik
und Wissenschaft (BTW2001), A. Heuer (Hrsg.), Informatik aktuell,
Oldenburg, März 2001. Springer-Verlag, S. 227-243
[Züllighoven et al. 98] Züllighoven et al. Das objektorientierte Konstruktionshandbuch. dpunkt Verlag, 1998
89
Herunterladen