Open Source-Perlen: Objekt-Persistenz mit Hibernate

Access-Layer pur

Stefan Edlich

Im zweiten Teil dieser Serie wird ein auf Sourceforge gehosteter Access-Layer vorgestellt. Hibernate verspricht das schnelle Speichern, Laden und Verändern der Java-Objekte einer Anwendung – ohne Codeänderungen wie bei JDO – und unterstützt eine Vielzahl von Datenbanken. Im Folgenden wird das Tool kurz vorgestellt und damit Anregung zur weiteren Beschäftigung mit diesem Access-Layer gegeben.

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]

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 mit

java cirrus.hibernate.tools.MapGenerator –output=Contact.hbn.xml Contact

die Mapping-Datei generiert werden, die die Member-Variablen auf die Datenbankspalten abpictureet:

......

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.

ds = Hibernate.createDatastore().storeFile(edlich.Contact);
sf = ds.buildSessionFactory();
se = sf.openSession();

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 updaten
Contact c2 = (Contact) sess.load(Contact.class, 42);
cat.setName("Mustermann");
sess.flush(); 

// Löschen eines Objektes
sess.delete(c3);

// Suchen von Teilinformation
String phone = se.find("select phone from Contact in class edlich.Contact where Contact.name = ,edlich'");

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.

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.

Geschrieben von
Stefan Edlich
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.