Auf der Suche nach geeigneten Möglichkeiten für die Speicherung seiner Objekte kommt man schnell auf die Idee, sich an EJBs, Objektdatenbanken oder neue magische JDO-Technologien zu wenden. Nicht so sehr geläufig ist allerdings die Menge der Mapper wie Toplink, die ohne obige Technologieansätze auskommen. Erst recht, wenn es darum geht, kostenfreie Open Source-Technologien zu verwenden.
Zu der letztgenannten Menge gehören Werkzeuge wie:
- Hibernate aus Sourceforge [1]
- dbgen aus Sourceforge [2]
- JAWS von JBoss [3]
In fünf Schritten zur Persistenz
Anders als andere clevere Access-Layer oder Frameworks " die in späteren Folgen vorgestellt werden " muss zwischen der Objektdefinition und der Speicherung des Objektes noch ordentlich Hand angelegt werden. Im Folgenden werden die Schritte beschrieben, wenn von Klassen ausgegangen wird aber noch keine mit Schema initialisierte Datenbank vorhanden ist. Die Möglichkeit des Reverse-Engineering aus einem Datenbankschema besteht bei Hibernate natürlich auch, wird aber hier nicht weiter betrachtet.Schritt 1: Klassendefinition
Klassen, die Hibernate speichern kann, sind normale Java Klassen, bei denen die Membervariablen ruhig privat sein können und getter/setter vorhanden sein müssen. Damit Hibernate nach einem load die gefundene Klasse auch instanziieren kann, muss sie einen leeren Default-Konstruktur haben. Für einige Tools oder cascaded-deletes ist weiterhin eine id nötig, die dem Primärschlüssel der Datenbank entspricht. Alle erbenden Klassen müssen obige Regeln ebenfalls beachten.Bei Bedarf können die Funktionen onSave(), onUpdate(), onDelete() und onLoad() implementiert werden, um selbst bei Persistenzaktionen Methoden auszuführen.
Schritt 2: Generierung der Mapping-Information
Sind alle Pfade korrekt gesetzt, so kann mitjava cirrus.hibernate.tools.MapGenerator --output=Contact.hbn.xml Contact
die Mapping-Datei generiert werden, die die Member-Variablen auf die Datenbankspalten abpictureet:
...<property name="version" column="version" type="int"/><property name="phone" column="phone" type="string"/>...
Schritt 3: Erzeugung und Ausführung des Datenbankschemas
Da hier von einer leeren Datenbank ausgegangen wird, wird ein Tool benötigt, das dass Schema erstellt und gleich auf der Datenbank ausführt:java -Dhibernate.dialect=cirrus.hibernate.sql.Datenbankdialekt -Dhibernate.connection.driver_class=datenbanktreiber -Dhibernate.connection.url=connectionURL -Dhibernate.connection.username=username -Dhibernate.connection.password=password cirrus.hibernate.tools.SchemaExport --output=Contact.ddl Contact.hbn.xml
Damit ist die Datenbank initialisiert und Objekte können nun im Java-Code gespeichert werden.
Schritt 4: Erzeugung von Datastore und Session
Im Java-Code ist ein Datastore zu erzeugen, indem die Mapping-Datei oder die Klasse angegeben wird. Auf dieser kann dann eine Session geholt werden, die das Arbeiten mit den Objekten ermöglicht:ds = Hibernate.createDatastore().storeFile(edlich.Contact);sf = ds.buildSessionFactory();se = sf.openSession();
Schritt 5: Schreiben, Suchen, Ändern und Löschen von Objekten
Im Folgenden sind einige Beispiele für Operationen mit Objekten angegeben. Dabei ist c1 genau das Objekt, welches entsprechend der ursprünglichen Klasse instanziiert wurde:Listing 1
sess.add(c1); // Speichern//Laden und danach updatenContact c2 = (Contact) sess.load(Contact.class, 42);cat.setName("Mustermann");sess.flush();// Löschen eines Objektessess.delete(c3);// Suchen von TeilinformationString phone = se.find("select phone from Contact in class edlich.Contact where Contact.name = ‚edlich‘");
Er kann aber noch mehr ...
Die hier gezeigten Beispiele haben hoffentlich neugierig gemacht. Selbstverständlich bietet Hibernate viele weitere Möglichkeiten, unter anderem die Folgenden:- Hibernate kann mit Collections umgehen und Dinge wie Map, Set oder Lists speichern.
- Die Query-Language erlaubt umfangreiche Abfragen wie table-joins, Aggregat-Funktionen (sum, avg, min, max, count) oder group by, having, order-by.
- Verschiedene Beziehungsarten und entsprechende suchen / cascaded deletes sind möglich.
- Der Datenzugriff ist Threadsave.
- Es sind diverse Cache-Mechanismen enthalten.
Fazit
Der Overhead, den Hibernate mittels Reflection und durch den generierten SQL Code erzeugt, ist in der Regel gering, daher ist der Code relativ schnell. In wenigen Fällen wünscht man sich dennoch von Hand eingreifen zu können, um Sonderfälle - wie zu langsame Abfragen über joins - zu optimieren.Bei Tests und im Projekteinsatz für viele Klassen ist es weiterhin wichtig, die Erzeugung der Zwischenschritte (Mapping-Datei erstellen, Schemainformation senden, etc.) aus Zeitgründen zu automatisieren. Die Erstellung der zugehörigen Ant-Tasks kostet auch hier einige Stunden und Nerven, da Beispiele entweder fehlerhaft sind, gänzlich fehlen oder sich schwer übertragen lassen. Eine gute Community sorgt aber auch hier sicherlich für baldige Hilfe.
Den Vergleich zu kommerziellen Profi-Werkzeugen (wie etwa dem Access-Layer aus dem Trend-Framework [4] oder Toplink [5]) muss Hibernate allerdings dennoch scheuen, da z. B. Wizards, Integration in Modellierungswerkzeuge, die Option des Verzichts auf vom Anwender erstellte Mapping-Dateien, Prototypengenerierung und einiges mehr fehlen. Für ein neues Projekt ist weiterhin abzuwägen, ob der Access-Layer auch die vielen Spezialbereiche wie logisches löschen, Versionierung der Objekte oder verschiedene Lockingstrategien - wie hierarchische Sperren auf Objekten - beherrscht.
Ist das Problem der Ant-Generierung von Mapping-Dateien und anderer Handarbeit aber einmal automatisiert, kann Hibernate jedoch für einfache Projekte als Access-Layer durchaus wertvolle Dienste leisten.




