Db4o

Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 24. Juni 2007 um 16:27 Uhr durch Brille (Diskussion | Beiträge) (Grundlegende API). Sie kann sich erheblich von der aktuellen Version unterscheiden.

db4o (Database for Objects) ist eine Objektdatenbank für Java und .NET. db4o zeichnet sich durch einen recht kleinen Footprint von etwa 600KB aus und eignet sich dadurch für die Einbettung in andere Programme und für Umgebungen mit knappem Speicher, wie beispielsweise PDAs.

db4o läuft nativ auf Javas JDK 1.1.x bis 6.0 und auch in der J2ME, sofern die Implementierung Reflection unterstützt. Daneben werden alle Sprachen unterstützt, die auf der CLR von .NET aufsetzen. Beispielsweise C# und VB.NET. Dadurch kann db4o ebenfalls als Server unter Windows und UNIX laufen.

Bekannte Firmen, die db4o einsetzen, sind:

  • BMW: Zur Aufzeichnung von Fahrzeugdaten
  • Bosch: Persistenz für Bosch Roboter, die Verpackungen für Nahrungsmittel in aller Welt produzieren und ständig neu konfiguriert werden müssen.
  • Indra: Echtzeit Datenerfassung in den Spanischen Hochgeschwindigkeitszügen.
  • Energieunternehmen / Deutsche Post: Hier wird db4o für die Datenfassung auf Clients wie Handhelds verwendet.
  • weitere Unternehmen: Seagate, Intel, Ricoh, Boeing und viele weitere

Systemeigenschaften und Objektmanagement

  • Neben dem kleinen Footprint ist auch der Verbrauch an RAM gering und überschreitet 1MB in der Regel nicht.
  • Db4o kann nicht von aussen administriert werden. Sämtliche Einstellungen müssen über den Code vorgenommen werden.
  • Die Datenbank kann auch in gemischen Umgebungen eingesetzt werden. Also zwei Anwendungen unter z.B. C# oder Java können auf eine Java oder C# Datenbank zugreifen. Mit Hilfe von Aliasen können sich dabei sogar die Klassennamen und Packages unterscheiden.
  • Eine der wichtigsten Vorteile von db4o: Objekte können einfach so gespeichert werden. Es ist keine Vererbung, kein Ableitung von speziellen Interfaces, kein AOP mäßiges Bytecode enhancement nötig. Das Objekt kann dabei beliebige Typen enthalten und zudem beliebig tief sein. Also Objekte in Objekten in Objekten etc. enthalten.
  • Mit dieser Eigenschaft ist es möglich, Objektinstanzen in weniger als 2 Minuten zu speichern. Inklusive Download und das jar / dll in den Classpath zu nehmen.

Grundlegende API

Unter API versteht man das Application Programmers Interface, d.h. die Programmierschnittstelle, mit der der Entwickler die Datenbank programmiert. Dabei zeigt sich, dass der Unterschied zu anderen Programmen wie Hibernate oder JPA / EJB nicht allzu groß ist.

Ein einfaches Codebeispiel, das zusammenhängend ausgeführt werden sollte:

   ObjectContainer db = Db4o.openFile("C:/beispiel.db");
   try { // Speichert zwei Objekte
      db.set(new Person("John Doe","TOP INC",45));
      db.set(new Person("Clara Himmel","BB Radio",30));
      
      ObjectSet result = db.get(new Person());
      while (result.hasNext()) { // Iteriere durch alle Objekte 
          System.out.println(result.next());
      }
      
      result = db.get(new Person("Clara Himmel"));
      Person found = (Person) result.next();
      found.setAge(25); // Wurde jünger
      db.set(found); // Objekt updaten
      db.delete(found); // Objekt löschen
      db.commit();
   }
   finally {
      db.close();
   }
  • Ähnlich zu EJB / JPA (dort EntityManager) erstellt man einen ObjektContainer. Der kann hier entweder auf eine Datei verweisen, oder ein Server- oder Client-Container sein. Im ersten Fall werden alle Datein in einer Datei gespeichert.
    • Nachteil: Die Daten sind also nicht komplett unabhängig von der Klasse der Programmiersprache. Das Format ist proprietär und kann ggf. von nachfolgenden Programmiersprachen nicht mehr so einfach gelesen werden.
    • Vorteil: Diese kann dan sehr leicht zwischen Firmen ausgetauscht werden. Der Datenzugriff ist sehr schnell.

Danach werden alle CRUD (Create, Read, Update und Delete) Operationen ausgeführt:

  • CREATE: Mit db.set(object) wird ein beliebiges Objekt gespeichert. Dies ist analog zum JPA Standard, wo man em.persist(object) aufruft. Allerdings muss man in letzterem Fall das Domain Objekt mindestens mit @Entity annotiert oder in XML registriert / gemappt haben.
  • READ: Es folgt eine einfache Suche mit der einfachsten Abfragesprache (s.u.) Query by Example. Eine Personinstanz wird als Template erstellt und beliebige Felder werden gesetzt. Zurückgegeben werden alle Objekt in der Datenbank, bei denen die Felder passen. found enthält daher das vollständige Objekt, das oben gespeichert wurde.
  • UPDATE: Dieses found Objekt wird jetzt intern referenziert und kann daher verändert .setAge(25)und nochmals gespeichert werden. Dann ist es aktualisiert. Im JPA Standard entspeicht dies einem em.merge(object), wobei das Objekt immer attached, also von der Session referenziert "gemerkt" werden muss.
  • DELETE: db.delete(object) löscht ein Objekt, das dem Objektmanager bekannt sein muss.

Abfragesprachen

Db4o bietet drei Abfragesprachen, die alle nicht allzuweit von dem Entfert sind, was Hibernate und JPA / EJB bieten:

Query By Example (QBE)

Query By Example Query_by_Example steht für Suche mit einem Template Muster. Die Grundlagen dafür wurden schon in den 70er jahren von Moshé M. Zloof in einigen Artikel gelegt. en:Hibernate_(Java) und db4o bieten dies in einer leicht abgeschwächten Version an.

Bei db4o kann wie oben gezeigt ein beliebiges Objekt erstellt werden. Danach wird entweder:

  • Kein Feld gesetzt, so dass alle Felder null sind. Oder es wird direkt eine Referenz auf die Klasse übergeben (z.B. Person.class). In diesem Fall werden alle in der DB gespeicherten Instanzen zurückgeliefert.
  • Es werden beliebig viele Felder gesetzt: Dann werden alle Objekte zurückgeliefert, bei denen das Template Objekt passt.
  • Es wird null übergeben. Dann werden alle Objekte aus der Datenbank zurückgeliefert.

Native Queries

Native Queries sind Abfragen in der Programmiersprache selbst. Also bei db4o z.B. in Java oder C#.

  • Vorteile: 1. Der Programmierer muss keine neue Sprache lernen (SQL). 2. Die Abfragen sind typsicher und 3. Refactoringfest. Fehler in Query Strings wie bei SQL werden daher nicht so leicht möglich und werden früh gefunden.
  • Nachteil: Die Erstellung der Abfrage ist jetzt komplett in der Hand der Entwickler und z.B. nicht in der Hand von Administratoren, die wie bei "Stored-Procedures" ein "Sicherheits-"Auge auf die Datenbank werfen. Weiterhin sind Native Queries nicht so mächtig wie entsprechende Konstrukte in anderen Abfragesprachen wie HQL oder JPQL, da hier im String mehr Schlüsselwörter (wie z.B. für Aggregations) zur Verfügung stehen.

Native Queries wurden z.B. in den untenstehenden Quellen beschrieben.

Dazu Beispiele in C# 3.0(Beispiele in Java sind unter der db4o Community Dokumentationsseite zu finden): var persons = db.Query<Person> (s => s.Age < 50); Entscheidend für den komfortablen Einsatz ist, ob und wie die Sprache Closures unterstützt. Ansonsten muss mit inneren Klassen und Anonymous Delegates gearbeitet werden, um mdie Abfrage als freischwebender Code einer Methode zu übergeben.

Der Code von Native Queries wird bei db4o nie ausgeführt, sondern z.B. zur Laufzeit gelesen und dann verarbeitet / ausgeführt.

Zum Vergleich von Native Queries und JPQL oder HQL sei hier auf Microsofts LINQ verwiesen. Microsoft konnte die Sprache verändern und so mächtige Abfragekonstrukte direkt in C# einbetten.

SODA / Criteria Queries

Intern werden Native Queries bei db4o auf SODA abgebildet / transformiert. SODA ist eine Anfragesprache, die schon sehr früh auf Sourceforge gehostet wurde und dort unabhängig weiterentwickelt wurde. Es handelt sich dabei um eine Sprache, bei der Objektbäume erstellt werden, die die Abfrage mittels Objekten einschränken. Sie sind daher mächtiger als Native Queries, aber wiederum schwerer zu erstellen (da der Code schwerer zu lesen ist).

Die SODA Abfragen ähneln denen von Hibernate Criteria Abfragen stark. Ein Beispiel:

  Query query=db.query();
  query.constrain(Person.class);
  query.descend("alter").constrain(50).greater();
  ObjectSet result=query.execute();

Hier wird die Abfrage zunächst auf die Klasse Person eingeschränkt. Danach weiter auf alle Personen, die älter als 50 sind.

Transaktionen

Mit dem öffnen des Containers aus obigem Beispiel wird eine Transaktion erstellt. Diese kann jederzeit mit db.comitt() oder db.rollback auf die Datenbank geschrieben oder zurückgerollt werden. Db4o garantiert dabei ein ACID verhalten. Alles innerhalb einer Transaktion entspricht den ACID Anfroderungen. Intern werden dabei alle Zugriffe auf die Datenbank innerhalb der Transaktion serialisiert. Dies hat schwerwegende Konsequenzen für das Datenbanksystem:

  • Durch das proprietäre Datenformat ist der Zugriff für einen Thread zwar meistens schneller als andere Datenbank / Mapper-Kombinationen.
  • Dennoch skaliert ein mMultithreaded" Zugriff nicht, wieder beispielsweise für den Bau von Großportalen nötig ist.

Erfahrungen zufolge sind bis zu einem Dutzend Zugriffe pro Sekunde in der Regel machbar, was auch für viele Web-Portale genügen sollte. db4o arbeitet daher an einer Serverversion, die auch multithreaded skaliert.

Client- / Server-Modes

Db4o bietet mehrere Arbeitsmodi an:

1. Embedded Mode: Es wird im Anwendungscode ein Objektcontainer eröffnet, wie in obigem Beispiel gezeigt. Basis ist hier ein filebasierter Zugriff.

2. Client / Server Mode: Db4o kann als Server gestartet werden und dann von Clients anfragen entgegen nehmen. Beispiel für den Server:

ObjectServer server = Db4o.openServer("c:/liveserver.db", 8732); server.GrantAccess("user1", "password"); server.GrantAccess("user2", "password"); Hier wird ein Thread geöffnet, der auf Clients listened. Der Server selbst kann über Monitore warten und beispielsweise Statusausgaben machen. Zugriffsrechte können wie bereits erwähnt nicht direkt von aussen mittels einem Tool verwaltet werden. Entweder werden diese im Code angelegt oder per Console etc. eingelsen.

Ein Client würde so aussehen.

aClient = Db4o.OpenClient("196.42.103.142", 8732, "user2", "password");

Mittels eines sogenannter "Out-Of-Band Signalling" Kommunikationsprotokolls können dem Server beliebige Objekte gesendet werden, mit denen ein Server dann administiert werden kann. Z.B. kann die Aufforderung zum Defragmentieren der Datei übermittelt werden.

Replikation

Sonstiges

Lizenz

db4o wird seit 2004 wahlweise unter der GPL als Open Source lizensiert oder unter einer kommerziellen Lizenz, die die Verwendung in nicht-GPL-Projekten erlaubt. Daneben gibt es eine Classpath ähnliche Lizenz, die es erlaubt, db4o in Open-Source Projekte zu integrieren, die nicht db4o / GPL konform sind.

Historie

Das db4o Projekt begann im Jahr 2000 unter Führung von Carl Rosenberger. Entwickelt wird db4o von der Firma db4objects, Inc., die 2004 mit Hilfe von Investoren wie Mark Leslie (VERITAS Software), Vinod Khosla (SUN Microsystems) und Jerry Fiddler (Wind River) gegründet wurde.

Native Queries:

  • William Cook, Carl Rosenberger, "Native Queries for Persistent Objects"
  • William Cook, Siddhartha Rai: Safe Query Objects, 2005

Beide Referenziert auf: http://www.cs.utexas.edu/~wcook