BigBastis Blog

Java: DB4O Anbindung in einer Client / Server umgebung

Introduction

user

Sebastian Gross

Sebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.


LATEST POSTS

Handling too long scrollspy menus 10th June, 2015

Java: Create ZIP archive 23rd March, 2015

Java

Java: DB4O Anbindung in einer Client / Server umgebung

Posted on .

Da ich mich zur Zeit selbst mit diesem Thema auseinander setze, dachte ich, es könnte nicht schaden ein kleines Tutorial zu schreiben. Hier möchte ich die ersten Schritte erklären und an ein paar Beispielen demonstrieren.

DB4O steht für Database for Objects und ist, wie der Name es schon sagt eine Datenbank für Objekte. Im Unterschied zu einer SQL Datenbank (wie MySQL) werden hier keine Tabellen erstellt, in denen die Daten gesichert werden, sondern die Objekte „als Ganzes“ in die Datenbank geschrieben.

Das bringt einen gewaltigen Vorteil, denn wenn man ein Objekt in einer herkömmlchen relationalen Datenbank sichern möchte muss man es in einzelne Teile zerlegen und diese Teile dann in die Tabellen schreiben. Beim Auslesen wieder das ganze Spielchen umgekehrt, man sucht sich alle Werte des Objekts wieder aus der Datenbank zusammen um dann eine neue Instanz davon zu erstellen und mit den alten Werten zu füllen.

All das ist mit DB4O nicht mehr nötig, da hier die Datenbank diese Aufgaben für uns übernimmt, somit ist es sehr einfach für uns auch sehr komplexe Objekte schnell und bequem zu sichern und zu laden.

Fangen wir aber ersteinmal mit der Installation an

Die Installation, wenn man diese so nennen kann ist bei DB4O sehr einfach, und besteht nur darin, die nötigen Librarys in das Projektverzeichnis zu kopieren. Somit ist keine Installation beim Client mehr nötig, das Programm bringt dann alles was nötig ist selbst mit!

Als erstes benötigt ihr die Librarys von der DB4O – Homepage

Nach dem ihr diese heruntergeladen habt erstellt ihr ein „lib“ Verzeichnis in eurem Projektordner.

In diesen neu erstellten Ordner entpackt ihr die *.jar Dateien aus dem heruntergeladenen Archiv aus dem gleichnamigen Ordner.

Nun wechselt ihr in Eclipse (bzw. eure IDE) und aktualisiert mal die Ansicht, ihr solltet nun den neuen Ordner mit den ganzen *.jar Dateien sehen.

Der letzte Schritt besteht darin, die Librarys zu dem Klassenpfad hinzuzufügen. Dazu klickt ihr mit der Rechten Maustaste auf euer Projekt und wählt „Properties“, dann wählt ihr rechts „Java Build path“, und nun den Tab „Libraries“.

Nun klickt ihr auf „Add JARs…“ und wechselt in euren lib Ordner. hier wählt ihr alle *.jar Dateien aus und klickt 2x auf „OK“. – Das wars auch schon!

Wenn das alles erledigt ist, sollte euer Projektbaum ca so auusehen wie auf dem Bild links.

Die Praxis

Wenn ihr die Installation schon einfach fandet, dann werdet ihr die Implementation lieben! Denn das ist genauso schnell erledigt, denn alle große Arbeiten übernehmen für uns die Libraries, die wir im letzten Schritt importiert haben!

Als erstes benätigen wir eine Klasse deren Objektinstanzen wir dann in die Datenbank schreiben können. Dazu habeich eine einfache kleine Klasse „Car“ geschrieben:

import java.io.*;
import java.util.*;

public class Car implements Serializable{
	private static final long serialVersionUID = 1L;
	private String marke;
	private int ps;

	private LinkedList teile = new LinkedList();

	// Konstruktoren

	public Car(){}

	public Car (int ps){
		this.ps = ps;
	}
	public Car(String marke){
		this.marke = marke;
	}
	public Car(String marke, int ps){
		this.marke = marke;
		this.ps = ps;
	}
	public void addTeil(String teil){
		teile.add(teil);
	}

	// Getter & Setter

	public LinkedList getTeile(){
		return teile;
	}
	public void setMarke(String marke){
		this.marke = marke;
	}
	public void setPs(int ps){
		this.ps = ps;
	}
	public String getMarke(){
		return this.marke;
	}
	public int getPs(){
		return ps;
	}
}

Wichtig ist bei dieser kleinen Klasse ist, dass sie das Interface java.io.Serializable implementiert, damit es auch selialisiert werden kann!

Ok nun haben wir ein Objekt, wie krigen wir dieses in die Datenbank? Das geht sehr einfach, wie man an diesem Codeschnippsel sehen kann:

    ObjectContainer db = Db4o.openFile
        ("C:/test.yap");
    try{
        db.set(new Car("VW", 124));
    }
    catch(DatabaseFileLockedException e){
        e.printStackTrace();
    }
    finally{
        db.close();
    }

Erst wird ein ObjectContainer erstellt, in den wir die Datenbankdatei einlesen, die bei DB4O die Endung yap haben. Wenn diese Datei noch nicht vorhanden ist wird diese automatisch angelegt. Hier gibt es zu beachten, dass die Pfadangabe nicht mit dem Windowstypischen „\“ (Backslash) angegebenwird, sondern mit einem normal Slash.

Im folgenden Try-Catch Block wird die Methode Set aufgerufen, der wir auch eine Instanz unseres Car-Objekts übergeben. Das wars auch schon, nun ist diese instanz der Car Klasse schon in der Datenbank gespeichert!

Genauso einfach geht es auch einene Wert aus der Datenbank wieder auszulesen:

bjectContainer db = Db4o.openFile
        ("C:/test.yap");
    try{
        ObjectSet result = db.get(new Car(null));
    }
    catch(Exception e){
        e.printStackTrace();
    }
    finally{
        db.close();
    }

Dazu wird die Methode Get benutzt, die als Rückgabewert ein ObjectSet mit allen Autos in der Datenbank liefert. Als Parameter wird der Get Methode eine leere Car Klasse übergeben, zu dem Warum komme ich nun.

Abfragesprachen / Abfragemethoden

Wie ihr an dem Letzten Codebeispiel gesehen habt wird hier keine SQL Sprache genutzt um die nötigen Werte aus der Datenbank zu ziehen, sondern es wird mit Objekten gearbeitet. DB4O bietet drei verschiedene Wege um an die gespeicherten Objekte zu kommen:

QBE – Query by Example
SODA – Simple Object Database Access
NQ – Native Queries

Ich werde hier aber nur auf die ersten zwei zusprechen kommen.

QBE bietet die einfachste Möglichkeit an unsere gespeicherten Objekte zu kommen, diese Methode habe ich auch bei dem Beispiel oben genutzt.

Bei dieser methode wird vom Benutzer ein Objekt erzeugt, nach dem dann in der Datenbank gesucht wird. Wenn wir den Fall von eben aufgreifen, wo nur eine leere Car Klasse übergeben wurde, werden wir sehen, dass der Wert null mit allen Werten übereinstimmt. Das heißt, will ich alle Werte aus der Datenbank haben, übergebe ich ihr eine „leere“ Klasse.

Wenn ich die Get Abfrage etwas ändere und statt null, „VW“ übergebe, würde uns die Datenbank alle Autos ausspucken, die als marke VW haben. Genauso können wir auch nach der PS Zahl suchen, indem wir statt null eine Zahl übergeben. Wir können aber auch, wenn wir genau wissen wonach wir suchen, auch beide Werte übergeben. db.get(„VW“,120);

Achting, wir können diese methoden nur anwenden, weil wir in der Car Klasse die einzelnen Konstruktoren definiert haben. So muss für jede Suchanfrage auch der passende Konstruktor vorhanden sein. Oder man erstellt einen Konstruktor, mit dem man alles abdecken kann. So könnte man in unserem Beispiel hier auch so vorgehen um alle VW Autos gelistet zu bekommen: db.get(„VW“, null);

Leider hat diese Vorgehensweise so simpel sie auch ist entscheidende Nachteile. So dürfen in den Konstruktoren keine Werte initialisiert werden, denn wenn ich im Konstruktor die Variable marke standardmäßig als marke = „VW“; initialisieren würde, würde mir die Datenbank bei jeder Suche nur Autos der marke VW ausspucken.

Desweiteren kann man keine Bedingungen benutzen, denn was ist wenn ich zB. alle Autos sehen will, die mehr als 100 PS haben?

Genau hier setzt SODA an. Hier sollte man wissen, dass alle Abfragen in DB4O unter der Haube in SODA laufen, so wird jede Anfrage automatisch konvertiert.

SODA bietet uns hier viele weitere Werkzeuge die man auch aus zB. SQL kennt. So können wir nun auch komplexere Abfragen erstellen. Setzen wir nun mal unser Problem von eben um und fragen alle Autos ab, die mehr als 100 PS haben:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

Wie man sieht ist diese Abfragemethode etwas komplexer. Aber auf den zweiten Blick ist es aber doch ganz logisch. Zu erst wird ein Query Objekt erzeugt, dem wir dann ein „constrain“ (zu Deut. Beschränkung, Begrenzung) übergeben. Diesem übergeben wir „Car.class“, somit sagen wir dem Query, dass er nur Objekte vom Typ Car aus der Datenbank holt.

Die nächste Zeile ist eigentlich auch selbsterklärend, dort setzen wir fest, dass die Ergebnisse absteigend (descend) sortiert werden, undzwar nach der Eigenschaft „ps“ und durch eine Weitere Beschränkung nur Werte über 100 akzeptiert.

Die letzte Zeile führt den Befehl aus.

Ähnlich kann man auch einen Maximalwert setzen, sodass nur Autos angezeigt werden die zwischen 100 und 130 PS haben:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

Natürlich kann man auch Autos abrufen, die einen bestimmten Wert enthalten. ZB alle Autos die die den Buchstaben w im Namen haben:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

Client / Server umgebung

So, nach der Kurzen Einführung wollen wir nun das eigentlich Ziel umsetzen, nämlich die Datenbank in ein Client Server System integrieren. Zum Glück ist das ebenfalls nicht allzu kompleziert!

Malen wir uns erstmal ein kleines Diagramm um zu verbiltlichen, wie der Aufbau der Programme sein soll:

Bild 2: Der Aufbau

Das Tolle ist, dass die DB4O Libraries und die Arbeit abnehmen eine Verbindugn aufzubauen, die Sockets zu verwalten und die einzelnen Threads anzulegen. Somit müssen wir uns nur auf die Implementierung konzentrieren.

Unsere Server Applikation ist dementsprechend sehr einfach gestrickt:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

Wie man sieht sieht man nicht viel. Was auffällt, ist dass man nun statt openFile openServer benutzt wird, und als zweiten Parameter nun einen Port mitgibt, auf dem der Server auf Verbindungen wartet.

Danach werden noch die Benutzer beschrieben, denen der Zugriff auf die Datenbank gewährt werden soll. Und eigentlich wars das auch schon! Die anschließende Schleife sorgt nur dafür, dass das Programm unendlich läuft (zumindest bis der Benutzer es terminiert) und Anfragen von Clients akzeptiert!

Gut nun schauen wir uns mal den Client an:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

Wie man sieht ist die Verbindung zum Server noch einfacher gestrickt als der Server. Es wird wiedermal ein ObjectContainer instanziert und kann nun genauso benutzt werden wie in den Beispielen von oben.

Ich denke mal das dürfte als Einstieg reichen. Wenn ihr Probleme oder Fragen habt könnt ihr diese hier gern posten, vielleciht kommt dann irgendwann ein zweiter Teil.

Ein Lauffähiges Beispiel gibts hier: Download [Eclipse Project]

Wer mehr erfahren will guckt hier.
Eine wetere gute Anleitung gibts hier.

profile

Sebastian Gross

http://www.bigbasti.com

Sebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.

Comments
user

Author bigbasti87

Posted at 13:20 12. Januar 2010.

Bloggd: Java: DB4O Anbindung in einer Client / Server umgebung – http://blog.bigbasti.com/java-db4o-anbin… #db4o #tutorial #java

Kommentar verfassen

View Comments (1) ...
Navigation