Open Source im professionellen Einsatz

Objektdatenbank Db4o für Java und Mono

Konservierungsmittel

Spätestens seit den 90er Jahren gehört objektorientiertes Programmieren zum flotten Alltag. Geht es um dauerhafte Speicherung, steigen Entwickler aber immer noch auf ein rostiges Dreirad um. Damit ist Schluss: Die Objektdatenbank Db4o konserviert mit wenigen Zeilen auch komplexe Objektstrukturen.

Im Kindergarten um die Ecke versucht einer der kleinen Wichte mit seinem Holzhämmerchen den runden Bauklotz durch das eckige Loch zu treiben. Nur einen Häuserblock weiter steht ein Programmierer vor dem gleichen Problem. Im Gegensatz zu seinem jüngeren Leidensgenossen versucht er jedoch ein Objekt in die Tabellen einer relationalen Datenbank zu pressen. Die Attribute sind noch recht schnell verstaut, die unterschiedlichen Referenzen und Vererbungshierarchien produzieren jedoch planmäßig ein nur schwer wartbares Tabellengeflecht.

Egal ob MySQL, Oracle oder DB2, keiner der etablierten Kameraden kann Objekte so richtig gut leiden. Java-Programmierer dürfen wenigstens zu der Krücke Hibernate [2] greifen, das Objekte nach einem manuell festgelegten Schema in eine Datenbank hämmert. Doch wehe dem, der schnell mal eben ein Refactoring durchführen möchte. Wie schön wäre doch eine spezialisierte Datenbank. So eine Art Container für Objekte, den man nur mit

ObjectContainer db=Db4o.openFile("adressdatenbank");

zu öffnen braucht, um dann irgendein zu speicherndes Objekt - beispielsweise »Kunde« - über eine entsprechende Methode dort hineinzuwerfen:

db.set(Kunde);

Die beiden Codezeilen gehören zur noch recht jungen Datenbank Db4o. Mehr ist tatsächlich nicht notwendig, um in ihr ein beliebiges Objekt dauerhaft zu konservieren. Db4o verzichtet komplett auf jegliche Tabellen und zählt damit zu den - noch recht seltenen - reinen Objektdatenbanken.

Zur Jahrtausendwende nahm Carl Rosenberger die Arbeiten an der "Database for Objects" auf. Die erste Version erschien 2001 und wurde vorwiegend an interessierte und testwillige Anwender abgegeben. Drei weitere Jahre vergingen, ehe die Software reif für die kommerzielle Vermarktung war. Eigens zu diesem Zweck wurde 2004 unter der Leitung von Christof Wittig die Firma Db4objects gegründet. Das Geld gaben drei alte Bekannte: Mark Leslie von Veritas, Vinod Khosla, Geschäftsführer bei Sun, und Jerry Fiddler von Wind River.

Noch im gleichen Jahr führte Db4objects ein zweigleisiges Lizenzmodell ein. Wer freie Software entwickelt, darf die Datenbank kostenlos unter den Bedingungen der GPL nutzen. Bei kommerziellen Anwendungen blutet jedoch der Geldbeutel. Obwohl Db4o im Vergleich zur etablierten Konkurrenz noch recht jung ist, kann es bereits einige prominente Nutzer vorweisen, darunter sind BMW, Boeing, Bosch und Intel.

Klein, aber oho!

Db4o arbeitet ACID-konform, unterstützt also die für Datenbanken grundlegenden Arbeitsprinzipien Atomarität (eine Transaktion wird ganz oder gar nicht ausgeführt), Konsistenz (Consistency, eine Transaktion hinterlässt einen konsistenten Zustand), Isolation (Transaktionen beeinflussen sich nicht gegenseitig) und Dauerhaftigkeit (Ergebnis der Transaktion bleibt dauerhaft gespeichert).

Wie bereits gezeigt, kann eine Db4o-Datenbank beliebige Objekte speichern. Der Programmierer muss sie nicht einmal von einer speziellen Persistenzklasse ableiten. Damit die Speicherung dennoch klappt, greift Db4o zu einem Trick: Über den Reflection-Mechanismus analysiert Db4o zunächst die Struktur des übergebenen Objekts und schiebt die dabei erbeuteten Informationen in seine Datenbank. Folglich benötigt man weder ein zuvor erstelltes Schema noch ein Mapping, wie es Hinernate verlangt. Umgekehrt bedeutet das aber auch, dass Db4o derzeit nur mit Java und Dotnet beziehungsweise Mono-Sprachen funktioniert. Alle nachfolgenden Beispiele verwenden Java, sind aber leicht auf C# übertragbar.

Zum Knuddeln

Db4o besteht aus einer einzigen kleinen ».jar«- beziehungsweise ».dll«-Datei. In gerade mal 700 KByte enthält sie die komplette Datenbank-Engine, die sich sogar noch auf bis zu zirka 400 KByte abspecken lässt. Das Leichtgewicht fühlt sich somit auch in Embedded Devices oder mobilen Geräten wohl.

Nach dem Download des aktuellen Db4o-Archivs unter [1] kopiert man die zur jeweiligen Sprachversion passende Bibliothek aus dem »lib«-Verzeichnis in das eigene Projektverzeichnis. Bei einem Java-5-Projekt wäre beispielsweise »db4o-6.0-java5.jar« der richtige Partner. Damit ist die Installation bereits erledigt und Db4o ist einsatzbereit. Im eigenen Programm sind nur noch die benötigten Packages beziehungsweise Namespaces zu importieren - und schon darf man beliebige Objekte eintuppern. Listing 1 zeigt noch einmal ein vollständiges Beispiel für das Speichern zweier Kunden in einer Adressdatenbank.

Die zentrale Anlaufstelle ist das »com.D4o«-Objekt (siehe Kasten "Extensions"). Es enthält verschiedene statische Methoden, die beispielsweise eine neue Datenbank produzieren oder eine existierende konfigurieren. In den meisten Fällen fordert ein Programmierer von ihr lediglich einen »ObjectContainer« an, der die Datenbank selbst und die Zugriffe darauf kapselt.

Extensions

Die Db4o-Programmierschnittstelle besteht eigentlich aus zwei Teilen. Alle Kernfunktionen, die auch in Zukunft unverändert bleiben, liegen im »com.db4o«-Package. Dazu gehören beispielsweise das zentrale »Db4o«-Objekt oder der »ObjectContainer«.

Neue oder wenig benutzte Funktionen packen die Entwickler in das »com.db4o.ext«-Paket. Darin befindet sich beispielsweise der »ExtObjectContainer«, der gegenüber seinem »ObjectContainer«-Kollegen ein paar Funktionen mehr auf Lager hat. Pfiffigerweise ist ein »ObjectContainer« auch immer gleichzeitig ein »ExtObjectContainer«. Um an einen »ExtObjectContainer« zu gelangen, genügt entweder ein simples Cast oder der Aufruf der »ObjectContainer.ext()«-Methode.

Diese Zweiteilung hat gleich mehrere Vorteile: Einsteiger werden nicht mit unnötigem Ballast bombardiert, die zusätzlichen Funktionen dürfen für eine abgespeckte Db4o-Variante wegfallen und - last but not least - können die Entwickler relativ gefahrlos neue Funktionen anbieten, ohne gleich das Db4o-Kern-API ändern zu müssen.

Umgekehrt bedeutet Letzteres aber auch, dass sich alle im »ext«-Namensraum verstauten Funktionen mit jeder neuen Db4o-Version ändern können. Ein prominentes Beispiel liefert das Replication-API.

Jede Db4o-Datenbank besteht aus einer einzigen Datei, die meist die Endung ».yap« führt, selbst im Client-Server-Modus. Im Beispiel aus Listing 1 heißt sie »adressendatenbank.yap«. In ihr landen alle per »db.set()« gespeicherten Objekte. Das Erstellen eines »ObjectContainer«-Objekts startet gleichzeitig eine Transaktion, die erst ein »db.commit()« explizit abschließt. Gleiches übernimmt »db.close()«, das zusätzlich noch den gesamten Container zusperrt. »db.rollback()« nimmt die jeweils letzte Transaktion zurück.

Listing 1: Speichern eines
Objekts in Java

01 package adressbeispiel;
02 import com.db4o.*;
03 import com.db4o.config.*;
04 import com.db4o.query.*;
05 
06 class Kunde
07 {
08     private String name;
09     private String adresse;
10     private int kundennummer;
11 
12     public Person(String name, String adresse, int kundennummer){
13         this.anrede = name;
14         this.name = adresse;
15         this.kundennummer = kundennummer;
16     }
17 
18     public String getName() { return name; }
19     public void setName(String name) { this.name = name; }
20     public String getAdresse() { return adresse; }
21     public int getKundennummer() { return kundennummer; }
22     public void print() {System.out.println(name + adresse + kundennummer);}
23 }
24 
25 public class Adressbeispiel {
26     public static void main(String[] args){
27         ObjectContainer db = Db4o.openFile("adressdatenbank.yap");
28         try{
29             Kunde herrbert = new Kunde("Herr Bert", "Hinkburg", 56321);
30             Kunde frauenbart = new Person ("Frau Enbart", "Neustadt", 98217);
31             db.set(herrbert);
32             db.set(frauenbart);
33         }
34         finally{
35             db.close();
36         }
37 
38      }
39 }

Das per »db.set()« übergebene Objekt landet nicht nur mit Haut und Haaren in der Datenbank, Db4o greift sich auch gleich noch sämtliche an ihm hängenden, respektive alle von ihm referenzierten weiteren Objekte (Persistence by Reachability). Zyklen und anderen Assoziationssalat löst die Datenbank dabei selbstständig auf. Damit stellt sich aber die Frage, wie man an das so verstaute Material wieder herankommt. Der angestaubte Abfrage-Großvater SQL ist auf relationale Datenbanken geeicht und funktioniert somit in diesem Fall nicht. Folglich muss eine neue Abfragesprache her. Db4o kennt davon sogar drei - mit jeweils eigenen Vor- und Nachteilen.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 6 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook