Objektorientierte und relationale Welt

Technologiebrüche beseitigen

10.12.2001
Objektorientierte Programmiersprachen erfreuen sich großer Beliebtheit. Doch die Anbindung an relationale Datenbanken macht Probleme. von Thomas Weihrich*

Sollen objektorientiert modellierte Daten in klassischen relationalen Tabellen gespeichert werden, führt dies zum Bruch der Datenmodelle - im Fachjargon "Impedance Mismatch" genannt. Objekte auf Tabellen abzubilden ist äußerst komplex und ohne Informationsverlust kaum möglich. Dies zeigt sich nicht nur an hohen Designkosten, längerer Entwicklungszeit und damit späterer Markteinführung (Time to Market), sondern es betrifft auch die Qualitätssicherung sowie die Wartung und Änderbarkeit des Codes während des Betriebs. Um den Bruch zwischen den konzeptionellen Welten zu überwinden, bieten Datenbankhersteller verschiedene Lösungsansätze.

Im Kern besteht das Problem in der Schwierigkeit, objektorientierte Strukturen auf das Datenmodell relationaler Datenbank-Management-Systeme (RDBMS) abzubilden. Dies erfordert eine Anpassung der gekapselten und in Klassenhierarchien gegliederten Objekte an das Schema flacher Tabellen. C++-Programmierer kennen dieses Problem bereits seit längerem. Mit der

Objekt versus Tabelle

wachsenden Verbreitung von Java rückt der "Impedance Mismatch" nun zunehmend auch in das Interesse einer breiteren Entwicklergruppe.

Objektorientierte (OO-)Programmiersprachen wie C++, Visual Basic, Delphi oder Java stellen Sprachelemente bereit, die sich nicht nur hervorragend dazu eignen, Bedienungsoberflächen zu entwickeln, sondern auch dazu, logische Probleme anzugehen. Sprachelemente wie Kapselung, Polymorphismus und Vererbung sind inzwischen so beliebt, dass kaum ein Anwendungsentwickler auf sie verzichten möchte. Allerdings müssen auch OO-Anwendungsentwickler zur dauerhaften Sicherung ihrer Daten auf einen permanenten Speicher, oftmals ein Datenbanksystem, zugreifen. Er basiert zumeist auf einem relationalen, objektorientierten oder postrelationalen Modell.

Das relationale Modell beschreibt alle Daten anhand eines standardisierten Formats von Tabellen mit Zeilen und Spalten. Zur Darstellung komplexer Datenstrukturen benötigt man meistens eine Vielzahl von Tabellen. Deren Verknüpfung lässt sich über externe Schlüssel - so genannte Foreign Keys - herstellen. Anweisungen und logische Operationen sind ebenfalls extern zu definieren und auszuführen, können aber oft über Stored Procedures aus der Datenbank heraus gestartet werden. Um effiziente Anwendungen zu entwickeln, braucht man eine tiefgehende Kenntnis der Tabellen, ihrer Beziehungen untereinander und der im Datenbanksystem verankerten Stored Procedures.

Das OO-Modell dagegen verbindet Daten und zugehörige Operationen zu einer Einheit (Objekt), die einem hierarchisch gegliederten System von Klassen angehört. Daten sind dabei als Eigenschaften, Verarbeitungsschritte als Methoden definiert.

Keine einfache Abbildung

Über Schnittstellen greift der Entwickler direkt auf die Methoden zu, ohne sich mit der Komplexität des darunter liegenden Codes auseinander setzen zu müssen. Zwischen Oberklasse und Unterklasse gibt es eine "Vererbung" genannte Beziehung, die dafür sorgt, dass die in der Oberklasse definierten Eigenschaften und Methoden automatisch allen Unterklassen zur Verfügung stehen. Ist auch Polymorphismus implementiert, können diese Komponenten in verschiedenen Unterklassen trotz gleicher Bezeichnung unterschiedlich sein, ohne dass das Anwendungen daran hindern würde, mit ihnen zu arbeiten.

Will man nun objektorientierten Code mit einer relationalen Datenbank verbinden, sind folgende Aspekte zu beachten:

- Assoziation von Objektklassen mit Tabellen: Die Hauptaufgabe besteht darin, die Eigenschaften jeder Klasse auf Tabellenspalten abzubilden. Im Regelfall erfordert das Objektmodell eine Klasse, die sich über mehrere Spalten einer Mehrzahl von Tabellen erstreckt. Oft werden auch auf dieselbe Tabelle mehrere Klassen abgebildet, welche die Informationen in der Tabelle jeweils gemäß ihren eigenen Bedürfnissen interpretieren. Eine einfache direkte Abbildung ist also nur selten möglich.

- Einfüge-Operationen: Beim Generieren eindeutiger Schlüssel (Unique Keys) im RDBMS ist es besonders wichtig, diesen Prozess mit dem Zuordnen von Objekt-IDs abzugleichen. Das erweist sich besonders dann als schwierig, wenn eine Objektklasse mehrere Tabellen im RDBMS umfasst. Die Zuordnung muss persistent sein, damit während der Programmausführung verschiedene relationale Zugriffe auf dasselbe Objekt erfolgen können. Außerdem ist dabei zu beachten, dass modifizierende Operationen (Insert, Update, Delete) in der richtigen Reihenfolge ablaufen.

- Serialisierung: Sie hat einen direkten Einfluss auf die Datenintegrität. Man muss sicherstellen, dass die verschiedenen Zugriffsstufen, die das RDBMS bietet, sich in den Persistenzmethoden der Klassen widerspiegeln.

- Evolution (Weiterentwicklung) der Schemata: Aufgrund der Abbildung objektorientierter auf relationale Daten muss die Weiterentwicklung des Objektschemas mit der des relationalen Schemas koordiniert verlaufen.

Um die Kluft zwischen neuen OO-Anwendungen und einer vorhandenen Datenbank zu überwinden, bieten sich vier Lösungsmöglichkeiten an:

1. Einsatz von OO-Erweiterungen relationaler Datenbanksysteme:

Obwohl die Hersteller relationaler Datenbanksysteme große Anstrengungen unternommen haben, OO-Elemente in ihre Datenbank-Engines zu integrieren, haben sie die Problematik noch nicht wirklich im Griff. Da keine dieser Engines objektorientiert implementiert ist, lassen sich Vererbung, Polymorphismus und Kapselung nicht auf die Schnelle in die Produkte integrieren. So bleibt dem Anwendungsentwickler am Ende doch nur die Manipulation einer quasi-objektorientierten Schicht über der eigentlichen, immer noch relationalen Datenbank-Engine.

2. Einsatz von Mapping-Tools zur Abbildung von Objekten auf relationale Datenbanken: Zur Abbildung von Klassen auf die Tabellen eines RDBMS bieten Hersteller zahlreiche so genannte Mapping-Tools an. Die darin enthaltenen Komponenten setzen eine Zwischenspeicherung (Caching) der Operationen ein, um den Datendurchsatz zu erhöhen, die Integrität der Datenbankoperationen sicherzustellen, eindeutige IDs zu generieren oder Bindings (Java Beans, COM-Objekte) für den Einsatz der zugehörigen Programmiersprache bereitzustellen. Zwar

Unterschiedliche Ansätze

sind derartige Tools recht effektiv, wenn es darum geht, ein relationales Schema für eine OO-Anwendung zu entwickeln. Nimmt die Komplexität der zu lösenden Probleme jedoch zu, landet die Verantwortlichkeit wieder in den Händen des Entwicklers. Dies gilt dann, wenn eine Klasse auf mehrere Tabellen oder mehrere Klassen auf eine Tabelle abzubilden sind.

3. Einführung einer objektorientierten Datenbank: Eine weitere Möglichkeit, den Bruch zu überwinden, besteht darin, auf eine rein objektorientierte Datenbank zurückzugreifen. Allerdings ist der Marktanteil dieser Datenbanken eher gering. Andererseits müssen RDBMS und OODBMS synchronisiert, das heißt Transaktionen in der RDBMS auch in der OODBMS sichtbar und verfügbar sein. Abgesehen davon bieten objektorientierte Datenbanken im Allgemeinen nur einzelne Bindings, etwa für C++, Smalltalk oder Java.

4. Einführung einer postrelationalen Datenbank: Postrelationale Datenbanken basieren auf assoziativen Arrays, die sich zugleich und ohne zusätzliche Mapping-Tools oder Caching-Schichten sowohl auf Objektmodelle als auch auf relationale Modelle projizieren lassen. Über Befehle, welche die assoziativen Arrays manipulieren, sind Persistenzmethoden in der Datenbank selbst implementiert und stehen dem Entwickler somit direkt zur Verfügung. Zugleich stellen die Datenbank-Engines eine relationale Ansicht derselben Daten bereit.

Die Implementierung zum Beispiel von Insert oder anderen SQL-Befehlen stützt sich auf dieselben Datenbank-eigenen Befehle, wie sie auch die objektorientierten Persistenzmethoden verwenden. Da multidimensionale Datenbank-Engines unabhängig von der Darstellung direkten und gleichzeitigen Zugriff auf die Daten ermöglichen, verringern sie die oben erwähnten Probleme der ID-Erzeugung,

Grenzen der Freiheit

Serialisierung und Weiterentwicklung. Allerdings verletzt der direkte Zugriff auf Tabellen und Stored Procedures das Prinzip der Kapselung und nimmt dem Entwickler die Freiheit, die Interna der Klasse neu zu implementieren, da sie aufgrund der relationalen Projektion offen gelegt sind.

Für die Entwicklung neuer Anwendungen oder die Weiterentwicklung bestehender Applikationen haben sich objektorientierte Programmiersprachen durchgesetzt. Unternehmen, die große Investitionen in relationale Datenbank-Technologie getätigt haben, müssen sich deshalb entscheiden, ob sie kurz-, mittel- oder langfristig den Auswirkungen des "Impedance Mismatch" zwischen den OO- und den relationalen Paradigmata begegnen wollen. Hiervon hängt ab, welcher der möglichen Lösungsansätze in die engere Wahl gezogen werden sollte. Dabei muss man auch prüfen, ob sich die betreffende Technologie einfach einsetzen und in bestehende Systeme integrieren lässt. Zudem sollte das Werkzeug hinreichend erweiterbar sein, um zukünftigen Anforderungen seitens Applikation und Datenbank zu genügen und den Einsatz neuer Entwicklungen wie XML oder SOAP zu ermöglichen.

Auch sollte dem Entwickler geholfen werden, den Code in der korrekten Schicht zu implementieren. Dann muss der Code nicht vom Datenbankserver auf einen anderen Server oder eine andere Schicht gehoben werden, um die Anforderungen der neu einzusetzenden Technologie zu erfüllen.