560 likes | 962 Views
Vorlesung Informationssysteme: „Neuere Konzepte “. Persistenz von Objekten. Dipl.-Inform. Michael Klein kleinm@ipd.uni-karlsruhe.de Dipl.-Inform. Heiko Schepperle schepperle@ipd.uni-karlsruhe.de. Details zu Teil I. I-1: Web und Datenbanken 1. Webinformationssysteme, JSP
E N D
Vorlesung Informationssysteme: „Neuere Konzepte“ Persistenz von Objekten Dipl.-Inform. Michael Klein kleinm@ipd.uni-karlsruhe.de Dipl.-Inform. Heiko Schepperle schepperle@ipd.uni-karlsruhe.de
Details zu Teil I I-1: Web und Datenbanken • 1. Webinformationssysteme, JSP • 2. Praktische Übung zu JSP • 3. Komponentenarchitekturen, EJB • 4. Web Services & Fragestunde I-2: Objektorientierte Datenbanksysteme • 1. Persistenz von Objekten
Persistenz von Objekten • Problem: Objekte einer objektorientierten Programmiersprache (wie Java) sind transient Bei Programmende verloren • Aber: Viele Anwendungen benötigen die Erhaltung bestimmter Objekte über das Programmende hinaus. Beispiele: Kundenobjekte, Bestellungsobjekt • Ziel daher: persistente Objekte
Anforderungen an Objektpersistenz Gewünschte Eigenschaften der Persistenz: • TransparenzBenutzer arbeiten in gleicher Weise mit transienten und persistenten Objekten. Persistenz erfordert keine Sonderbehandlung bei der Programmierung • InteroperabilitätPersistente Objekte können auch in anderen als der Erstellungsumgebung verwendet werden UND das Festschreiben ist von konkreten Persistenzsystemen unabhängig. Laufzeitumgebung und persistenter Speicher sind austauschbar • Skalierbare WiederauffindbarkeitDas Auffinden von persistenten Objekten erfolgt ohne vollständiges Durchsuchen des Objektpools • Mehrbenutzer, Konflikterkennung, Verteilung
Persistenztechniken (1) • Welche Persistenztechniken für (Java-)Objekte gibt es? BRAINSTORMING
Persistenztechniken (2) • 1) Objektserialisierung • 2) Manuelles Objekt-Relationales Mapping • 3) OR-Mapping-Tools • Einfache Mapper • Container Managed Persistence (EJB2) • NEU: Java Data Objects (JDO) • 4) Objektorientierte Datenbanksysteme (OODMBS)
Technik 1: Objektserialisierung - Idee • Idee: Wandle Objekt in einen Bytestrom um und lege diesen in einer Datei auf dem Filesystem ab. b1 : Bestellung peter : Kunde Artikelnr = 887 name = „Peter Pan“ kundennr = 12345 b2 : Bestellung Artikelnr = 998 1 0 0 1 1 0 0 0 1 0 1 1 0 1 0 0 1 1 1 0 0 1 Dateisystem Persistentes Medium
Objektserialisierung in Java • In Java durch zwei Streams: ObjectOutputStream, ObjectInputStream • Standard-Methoden: void writeObject(Object o)Object readObject() • Für Ablage in Datei: Umleiten der Ströme z.B. in FileOutputStream / FileInputStream Beispiel: Kunde peter = new Kunde(); peter.name = „Peter Pan“; peter.kundennr = 12345; peter.bestellungen = {new Bestellung(887), new Bestellung(998)}; FileOutputStream out = new FileOutputStream(„peter.ser"); ObjectOutputStream s = new ObjectOutputStream(out); s.writeObject(peter); s.close(); out.close();
Was wird serialisiert? Was wird von Objekt o serialisiert? • o‘s Klasse (im Beispiel also „Kunde“) • Signatur von o‘s Klassen (z.B. public etc.) • Werte von o‘s Attributen • wenn sie nicht als „transient“ markiert sind und • wenn sie nicht statisch sind • Weitere Objekte, auf die o‘s Attribute verweisen Generell gilt: Klassen, die serialisiert werden können, implementieren das leere Interface „Serializable“. Aufruf von writeObject auf Objekte, deren Klasse nicht Serializable implementiert, führt zu Exception.
Serialisierung – Bewertung • Transparenz • Nicht gegeben. Klassen müssen von Hand serialisiert/deserialisiert werden. • Interoperabilität • Problematisch. Feste Bindung an Java (sogar spezielle Versionsbindung). Generell aber unabhängig von verwendeter Speichermethode. • Skalierbare Wiederauffindbarkeit • Nicht gegeben. Objekte müssen vollständig (inkrementelles Laden nicht möglich) im Hauptspeicher deserialisiert werden, um Bedingungen testen zu können. Einfache Technik, aber nur für kleine Datenbestände
Kunde Bestellung name kundennr artikelnr kundennr JDBC RDBMS 887 998 12345 12345 Peter Pan 12345 T 2: Manuelles objekt-relationales Mapping • Idee: Bilde Klassen und Beziehungen als Relationen ab und speichere Objekte per JDBC in relationalem DBMS mit diesem Schema b1 : Bestellung peter : Kunde artikelnr = 887 name = „Peter Pan“ kundennr = 12345 b2 : Bestellung artikelnr = 998
OR-Mapping: Probleme • Grundproblem:Objektorientiertes Modell ist mächtiger als relationales Modell nur verlustbehaftete Abbildung möglich Probleme: • Methoden: nicht abbildbar • Objektidentität: nur durch künstliche Schlüssel • Klassenzugehörigkeit: Schwierig, nur durch externes Zusatzwissen • Vererbunghierarchien: unter Abstrichen (siehe später)
Grundsätzliche Abbildungsvorschriften Klasse k • Relation k • dabei eindeutige Attributfolge als Schlüssel s festlegen • Attribute von k geben Attribute der Relation 1:n-Beziehung b zwischen k und m • Schlüssel von k wird als Fremdschlüsselattribute in m aufgenommen. Attribute von b werden in m aufgenommen. n:m-Beziehung b zwischen k und m • neue Relation b mit folgenden Attributen • Schlüssel aus k • Schlüssel aus m • Attribute der Beziehung b (falls vorhanden)
Abbildungsvorschriften – Vererbung (1) • Möglichkeit 1: Alle Attribute in die Blattklassen ziehen und nur diese als Tabellen umsetzen • Student(nr, name, matnr) • Professor(nr, name, rang) • Assistent(nr, name, stundenzahl, fachgebiet) • Programmierer(nr, name, stundenzahl, sprache) • Charakteristika: • Es kann keine Objekte von inneren Klassen geben. • Vererbungsbeziehung nicht mehr ersichtlich • Kein Verbinden (Join) von Relationen nötig Vererbung Person nr name Student Professor Mitarbeiter matnr rang stundenzahl Assistent Programmierer fachgebiet sprache
Abbildungsvorschriften – Vererbung (2) • Möglichkeit 2: Jede Klasse als Relation nur mit ihren eigenen Attributen und dem Schlüssel • Person(nr, name) • Student(nr, matnr) • Professor(nr, rang) • Mitarbeiter(nr, stundenzahl) • Assistent(nr, fachgebiet) • Programmierer(nr, sprache) • Charakteristika: • Objekte auch von inneren Klassen • Vererbungsbeziehung gut nachgebildet, aber nur durch Zusatzwissen erkennbar • keine redundanten Attribute außer Schlüssel • Attribute von Objekten blattnaher Klassen müssen mit aufwändigen Joins gesammelt werden Vererbung Person nr name Student Professor Mitarbeiter matnr rang stundenzahl Assistent Programmierer fachgebiet sprache
Abbildungsvorschriften – Vererbung (3) • Möglichkeit 3: Jede Klasse als Relation mit allen (d.h. auch geerbten) Attributen und dem Schlüssel • Person(nr, name) • Student(nr, name, matnr) • Professor(nr, name, rang) • Mitarbeiter(nr, name, stundenzahl) • Assistent(nr, name, stundenzahl, fachgebiet) • Programmierer(nr, name, stundenzahl, sprache) • Charakteristika: • Objekte auch von inneren Klassen • Vererbungsbeziehung nur durch Zusatzwissen erkennbar • Redundante Attribute Fehleranfälligkeit, Änderungsaufwand • Keine Joins nötig Vererbung Person nr name Student Professor Mitarbeiter matnr rang stundenzahl Assistent Programmierer fachgebiet sprache
Abbildungsvorschriften – Vererbung (4) • Möglichkeit 4: Eine Relation, die alle Attribute und zusätzlich einen Typ enthält. Nicht benötigte Attribute werden mit NULL belegt. • Person(personentyp, nr, name, matnr, rang, stundenzahl, fachgebiet, sprache) • Charakteristika: • Vererbungshierarchie nicht mehr erkennbar • Relation stark aufgebläht mit vielen NULL-Werten • Da nur eine Relation: keine Joins nötig Vererbung Person nr name Student Professor Mitarbeiter matnr rang stundenzahl Assistent Programmierer fachgebiet sprache
Abbildungsvorschriften – N-äre Beziehungen Mehrstellige Beziehungen als Relation, die Schlüssel aller beteiligten Relationen sowie eigene Beziehungsattribute enthält. note Professor Vorlesung 0..1 0..* name uni rang name sws prüft 0..* Student matnr fach • Prüfung(profName, profUni, vorlesungName, matnr, note)
OR-Mapping – Bewertung • Transparenz • Nicht gegeben. Objekte müssen eigenständig (durch spezielle Methoden) dafür sorgen, dass sie per JDBC persistent gehalten werden. Zudem: Abstriche bei der Abbildbarkeit. • Interoperabilität • Gegeben, sofern OR-Umsetzung keine programmiersprachen- oder DBMS-spezifischen Funktionen verwendet. • Skalierbare Wiederauffindbarkeit • Gegeben, wenn OO-Anfragesprache (z.B. OQL) genügend gut in eine relationale Anfragesprache (z.B. SQL) transformiert werden kann. • Geeignet, wenn Datenmodell nicht zu komplex (d.h. wenige Klassen, flache Hierarchien, keine langen Beziehungsketten) • Hoch skalierbare Technik, aufgrund langjähriger Erfahrung mit dem rel. Modell und ausgereiften, leistungsfähigen RDBMS.
Technik 3: OR-Mapping Tools Idee: Füge zwischen Anwendung und RDBMS eine zusätzliche Softwareschicht ein, die das OR-Mapping automatisch und transparent durchführt. OO-Anwendung Java Klassen, Objekte OR-Mapping-Schicht JDBC, SQL Relationen, Tupel RDBMS
Generelle Probleme bei OR-Mapping-Tools Hauptspeicherobjekte: • Anwendungen greifen direkt auf Variablen und Methoden zu, verändern Instanzvariablen. ORM-Schicht muss dies erkennen und die Änderungen in die DB übertragen. • Mehrere verteilte Anwendungen können auf das gleiche Objekt zugreifen (hier z.B. Objekt 3). OO-Anwendung1 OO-Anwendung2 1 2 3 3 4 5 Objekt Objekt OR-Mapping-Schicht OR-Mapping-Schicht Tupel Tupel RDBMS 1 2 3 4 5 6 7 8 9 A B
Generelle Ansätze Generelle Ansätze: • Direkte Mapper • Container Managed Persistence (wie in EJB2) • Bytecode-Postprozessor (wie in Suns JDO)
Direkte Mapper (1) • Tool zum Hinzufügen zusätzlicher Methoden, die Abbildung von Instanzvariablen zu Tabellenspalten durchführen. MyClass MyClass Tool (mittels Reflection oder Metafile meist in XML) attr1 attr2 attr3 attr1 attr2 attr3 MyClass read(key) void update() • geerbt von Oberklasse oder • im Quellcode hinzugefügt Read: Fragt DB mittels JDBC/SQL ab und erzeugt aus Ergebnis das Objekt Update: Überprüft per Attributvergleich auf Änderung und schreibt ggf. zurück
Direkte Mapper (2) Probleme • Generell: Zugriffe auf Objekt werden nicht abgefangen. Daher: • Problematisch, wenn mehrere Anwendungen das gleiche Objekt verändern und zu unterschiedlichen Zeitpunkten zurückschreiben Konflikte, die nicht erkannt werden • Kein Nachladen von Objektgraphen möglich. Bei read wird Objekt und alle abhängigen Objekte geladen Geeignet für: • Dokumentartiges Verarbeiten von Objekten (z.B. CAD) • Alleine komplett einladen, editieren, speichern. • Nicht: freingranulares Laden/Schreiben von Einzelobjekten
Direkte Mapper (3) Bekannte Tools: • Castor/JDOcastor.exolab.org • JRelationalFrameworkhttp://jrf.sourceforge.net/ • Turbine/Torque jakarta.apache.org/turbine/torque/ • Hibernate http://hibernate.sourceforge.net/ • Cayenne http://objectstyle.org/cayenne/
Container Managed Persistence (EJB2) • Idee: Verwende zum Zugriff auf Instanzvariablen get/set-Methoden. Diese werden abstract definiert und automatisch generiert. Beziehungen zwischen Klassen werden im Deployment-Deskriptor abgelegt.
Container Managed Persistence (2) Kunde Kunde name: String name: String Descriptor Dateien <<abstract>>getName() : String setName(String) getBestellung() : Collection<Bestellung> setBestellung (Collection<Bestellung>) getName() : String setName(String) getBestellung() : Collection<Bestellung> setBestellung (Collection<Bestellung>) Generator 1 0..* Containermanager implementiert Methoden so, dass er Änderungen am Objekt abfangen und entsprechend darauf reagieren kann. Bestellung
CMP – Probleme Probleme: • get/set-Methoden abstrakt keine weitere Geschäftlogik kann eingebaut werden • Viele Descriptor-Dateien nötig. Abhilfe schaffen Generatoren wie XDoclet oder EJBGen
Bytecode-Postprozessor Idee: Verändere Bytecode so, dass Zugriffe auf Instanzvariablen abgefangen und entsprechend verarbeitet werden. Beispieltechnik: Java Data Objects (JDO) Quelldateien .java JDO Persistenz- Definitionen javac JDO Enhancer Bytecodedateien .class Enhanced Bytecode .class
Bytecode-Postprozessoren Probleme: • Änderungen am Bytecode kritisch • Veränderte Semantik für den Programmierer nicht direkt ersichtlich • Auch Nicht-JDO-Klassen müssen verändert werden • Konflikte mit anderen Postprozessoren • Verlangsamte Kompilierung
OR-Mapping-Tools – Bewertung • Transparenz • Eingeschränkt gegeben. Nutzer muss sich über veränderte Semantik im Klaren sein. Einschränkungen bei get/set-Methoden. • Interoperabilität • Nicht gegeben. Anwendung ist fest an das ORM-Tool gebunden. Austausch meist nicht möglich, da Code/Bytecode speziell verändert. • Skalierbare Wiederauffindbarkeit • Gegeben. Spezielle Anfragesprachen (OQL, JDOQL, EJBQL) werden auf SQL gemappt und direkt im RDBMS ausgeführt.
Technik 4: Objektorientierte DBMS Idee: Erstelle mehrschichtiges System, das speziell auf das Speichern und Wiederauffinden von Objekten ausgelegt ist. Dazu: Verwandle Objekte in flache Strukturen (Records, Tupel, Arrays etc.) und lege diese unter Verwendung von bekannten DB-Indexmechanismen (B-Baum, Hashtable etc.) direkt auf den Seiten der Festplatte ab.
OODBMS – Beispiel O2 Beispiel: O2-Systemarchitektur • Objekterzeugung, Objektlöschung • Auffinden von ObjektenD Object Layer • Zuordnung: OID HSp-Adresse • Behandlung von Objektzugriffsfehlern • Freispeicherverwaltung Memory Management Lr. ........Client......... Communication Layer • Objektversendung evtl. über Netzwerk • Persistente Ablage • Speicherverwaltung • Indizierung • Transaktionsmanagement Storage Layer Server
Persistenz durch Erreichbarkeit • Welche Objekte werden persistent gespeichert? • Solche, die direkt unter Namen abgelegt werden • Wurzelelemente • Solche, die von persistenten Objekten erreichbar sind • Solche, die in persistenten Kollektionen enthalten sind
Bekannte OODBMS (für Java) • Ozone • FastObjects • CudenDB • db4o • Jeevan • JYD Object Database • PJODe • SOD • VORTeX01 • XL2 Weitere unter: http://dmoz.org/Computers/Software/Databases/Object-Oriented/
OODBMS – Bewertung • Transparenz • Gegeben. Ermöglicht objektorientiertes Arbeiten ohne Impedance Mismatch. • Interoperabilität • Nicht gegeben. Feste Bindung an OODBMS und dessen API. • Skalierbare Wiederauffindbarkeit • Gegeben durch skalierbare Indexmechanismen • zudem: weitere Datenbankfunktionalität wie Transaktionsschutz, Mehrbenutzerfähigkeit etc.
FastObjects FastObjects • Java-Datenbank • Grundsätzliches Vorgehen: Veränderung des Java-Bytecodes mittels Enhancer • Persistenz durch Erreichbarkeit • Homepage: http://www.versant.net
FastObjects - Produkte • FastObjects ist kommerzielles Produkt: • Produkte: • FastObjects j2: Reine Java-DB, sehr klein (450 kB), nur 1 Benutzer, kein OQL, keine Benutzer • FastObjects e7: Java/C++-DB, alle Features, nur 1 Benutzer • FastObjects t7: Komplett-DB, mehrere Benutzer • Alle kostenpflichtig • Kostenfreie Varianten • FastObjects j1 (Community Edition): ähnlich j2, Community-Registrierung erforderlich. Nur für nicht-kommerziellen/akademischen/privaten Einsatz • Trial-Edition: ähnlich e7, Registrierung erforderlich, nur 30 Tage lauffähig
Persistenzfähige Klassen • Klassen müssen explizit als persistenzfähig gekennzeichnet werden, so dass deren Objekte in FastObjects speicherbar sind. • Angabe in der Konfigurationsdatei ptj.opt • Persistenzfähige Klassen werden von einem Enhancer verändert. • Klassen, die persistenzfähige Klassen verwenden, selbst aber nicht persistenzfähig sind, werden als persistenzbewusst (persistence aware) bezeichnet und auch verändert.
Erstellung einer Datenbank .java Quellcode javac .class Normaler Bytecode Persistenz-konfiguration ptj.opt Enhancer ptj Persistenzfähiger Bytecode und Datenbank-Verzeichnisse .jdo schemabase Ausführung mit normalem java-Befehl
Persistenzkonfigurationsdatei Aufbau der ptj.opt-Datei: [schemata\<Name des Schemas>] name = <Name des Schemas> [databases\<Name der DB>] name = <Name der DB> schema = <Name des Schemas> <FÜR ALLE PERSISTENZFÄHIGEN KLASSEN> [classes\<Klassenname>] persistent = true hasExtent = <true oder false> schema = <Name des Schemas>
Neue Kollektionstypen Persistenzfähige Kollektionstypen in FastObjects: Im Paket: com.poet.odmg.util: • BagOfObject • SetOfObject • ListOfObject • ArrayOfObject Standardmethoden: add, remove, clearAll, iterator etc.
Transaktionen Alle Datenbankoperationen müssen in Transaktionen gekapselt werden: Transaktion = Object der Klasse com.poet.odmg.Transaction Erzeugen einer Transaktion = Objekterzeugung: • Transaction tr = new Transaction(); Beginnen einer Transaktion = Methodenaufruf: tr.begin(); Beenden einer Transaktion = Methodenaufruf: • tr.abort(); • tr.commit();
Öffnen und Schließen der Datenbank Komplette Datenbank wird durch Objekt der Klasse com.poet.odmg.Database repräsentiert. Vorgehensweise: • Erzeugen: Database db = new Database() • Öffnen: db.open(URL, Zugriffstyp) • URL = FastObjects://LOCAL/<DBNAME> • Zugriffstyp: Database.OPEN_READ_WRITE, Database.OPEN_READ_ONLY • Arbeiten mit der Datenbank innerhalb von TAs • Schließen: db.close()
Beispiel-Datenbank: Web-Shop Person Warenkorb Artikel 1 0..1 0..* 0..* käufer enthält name:String preis: doubletitel: String 1 getGesamt- preis() : double 0..* Buch CD DVD autorVon isbn : String interpret : String laenge : int laenge : int
Erzeugen und Benennen von Objekten Erzeugen von persistenzfähigen Objekten durch gewöhnlichen Konstruktoraufruf: • DVD harryPotter = new DVD(„Harry Potter“); Das Objekt ist dann noch nicht persistent. Es muss dazu explizit bei der DB unter einem Namen bekannt gemacht werden: • <Datenbankobjekt>.bind(<Objekt>, <Name>); • db.bind(harryPotter, „dvd28“); Hierbei können Exceptions auftreten: • ObjectNameNotUniqueException • ObjectNotPersistentException • NoUniqueTransactionException
Entnehmer benannter Objekte Benannte Objekte können mit der lookup-Methode wieder aus der DB entnommen werden: • Object o = <Datenbankobjekt>.lookup(<Name>); • Object o = db.lookup(„dvd28“); Das Object muss dann noch in den richtigen Typ konvertiert (gecastet) werden: • DVD harryPotter = (DVD)o; Mögliche Exceptions bei lookup: • ObjectNameNotFoundException • NoUniqueTransactionException
Löschen persistenter Objekten Löschen eines persistenten Objekts mit Hilfe der deletePersistent-Methode: • <Datenbankobjekt>.deletePersistent(<objekt>); • db.deletePersistent(harryPotter); Die Methode funktioniert nur, wenn das persistente Objekt von keinem anderen persistenten Objekt referenziert wird.
Extents - Idee • Idee: Extent= Menge aller Objekte einer bestimmten Klasse (inkl. Objekte aller Unterklassen) • Stehen automatisch für alle Klassen zur Verfügung, die in der Persistenzkonfiguration „hasExtent = true“ haben. Sie müssen daher nicht mit add/remove-Methoden verwaltet werden. • Erstellung eines Extents: • Konstruktoraufruf: Extent e = new Extent(<Klassenname>) • Funktioniert nur, wenn genau eine DB offen und genau eine Transaktion gestartet ist, sonst komplexere Konstruktoren