# Mit welcher Technologie Daten abspeichern?



## SebiB90 (4. Jun 2009)

Hi,

ich bin grad am überlegen, wie ich die Speicherung in meinem Programm machen soll. Ich will die Daten als XML Datei abspeichern. Mir stellt sich jetzt nur noch die Frage mit welcher Technologie ich das umsetzen soll. Ob JAXB, JDom, Eclipse Link? Oder oft hab ich hier in letzter Zeit gesehen, dass man auf EMF verwiesen wurde, als es um JAXB ging. Klappt es damit auch? Dann mal paar Infos, damit ihr wisst worum es überhaupt geht:

Ich habe eigentlich nur 3 Datenklassen: Kunde, Ware, Transaktion.
Kunde und Ware haben allgemein nur ein Namen und ein Preis bzw. Guthaben und eine ID zur eindeutigen Identifikation. Der Kunde hat eine Liste mit seinen Transaktionen.
Transaktion hat auch eine ID, ein Typ und eine Referenz auf einen Kunden und auf eine Ware.
Also ich habe jeweils eine 1:n Beziehung zwischen Kunde und Transaktion sowie Ware und Transaktion. Dabei soll die Verbindung der Klassen in der XML so realisiert werden, dass die ID des jeweiligen Kunden bzw der jeweiligen Ware in der Transaktion gespeichert wird. (Hab bisher bei JAXB Beispielcodes gesehen, dass die Attribute, auch wenn es Klassen sind, direkt an der Stelle in die XML geschrieben wurde. Das kann ich aber nicht gebrauchen, brauche nur eine Referenz, da ein Kunde nun mal mehrere Transaktionen hat und ich nicht den Kunden mehrfach speichern will).

In meinem Programm arbeite ich momentan mit DAO Interfaces. Sprich für jede Datenklasse ein DAO Interface. Die momentane Dummy Implementierung sieht so aus, das jede DAO Klasse eine HashMap hat und da drin die Objekte gespeichert werden. Wenn ich jetzt über JAXB die Speicherung implementiere, muss ich dann noch eine weitere Klasse erstellen, die dann diese 3 HashMaps beinhaltet und diese dann abspeichern? Weil alle einzeln abspeichern, geht das überhaupt?

Die XML soll grob dann so aussehen:
[XML]<kassensystem>
  <kunden>
    <kunde>
      <id>1</id>
      <name>SebiB90</name>
      <guthaben>1000</guthaben>
    </kunde>
    ...
  </kunden>
  <waren>
    <ware>
      <id>1</id>
      <name>Auto</name>
      <guthaben>10000</guthaben>
    </ware>
    ...
  </waren>
  <transaktionen>
    <transaktion>
      <id>1</id>
      <typ>Kaufen</typ>
      <kunde refid="1" />
      <ware refid="1" />
    </transaktion>
    ...
  </transaktionen>
</kassensystem>[/XML]

Man merkt wohl, das ich in dem Bereich noch ziemlich unerfahren bin und baue auf eure Hilfe. Was würdet ihr für das Problem vorschlagen? Ahja, noch eine Sache: Es sollte möglichst eine transaktionsbasierte Speicherung sein, also in der Regel wird eine Save Methode vom KundenDAO und TransaktionDAO hintereinander ausgeführt und wenn bei einem ein Fehler auftritt, muss ein Rollback ausgeführt werden, sonst gibts Probleme =/

Danke schonmal im vorraus.

Mfg
SebiB90


----------



## Noctarius (4. Jun 2009)

Am einfachsten ist JAXB aber auch nicht so richtig schnell find ich, zumind bei großen Datenmengen (XML über 30.000 Zeilen) .

Absolut mächtig und auch von der Geschwindigkeit her ist EclipseLink, da ich damit aber selbst derzeit erst ein wenig rumspiele und noch in den Anfängen bin, kann ich dir noch nicht so unheimlich viel dazu sagen. Aber was ich bisher gesehen habe gefällt mir EL sehr gut.


----------



## SebiB90 (4. Jun 2009)

Danke schonmal für die Antwort.
Wenn ihr gute Tutorials (bevorzugt deutsch) zu den Technologien kennt, her damit 
Da mir sowas (am Beispiel von EL) EclipseLink/Examples/MOXy - Eclipsepedia nur wenig bringt. Macht mir nur wenig schlauer.


----------



## Wildcard (4. Jun 2009)

Ich würde dir zu EMF raten. Ist ein extrem mächtiges und flexibles Framework  und am ende bist du völlig wahlfrei in der Art der Persistierung. XML, EclipseLink, Hibernate, FlatFiles, was auch immer.


----------



## SebiB90 (4. Jun 2009)

Wildcard hat gesagt.:


> Ich würde dir zu EMF raten. Ist ein extrem mächtiges und flexibles Framework  und am ende bist du völlig wahlfrei in der Art der Persistierung. XML, EclipseLink, Hibernate, FlatFiles, was auch immer.



Könntest du mir dazu nen gutes Tutorial geben?
Weil irgendwie überblick ich das nicht so wirklich. Da es ja so einiges kann, weiß ich nicht an welcher Ecke ich da anfangen soll.

Und wäre es einfach mit meiner bisherigen Struktur das umsetzen. Sprich über meine bisherigen DAO Interfaces, die halt standard CRUD Operationen (save, delete, find..) anbieten, und das bisherige Datenmodel. Oder wären diese hinderlich und meine Service Klassen, die die DAOs verwenden, sollten direkt aufs EMF zugreifen und das Datenmodel muss nach einem bestimmten Schema aufgebaut sein dafür? Weil beim überfliegen sehe ich was, das die Datenklassen von EObject erben oder so. Naja wie gesagt, absolut null plan von EMF.


----------



## Wildcard (4. Jun 2009)

Ist wirklich nicht schwer. Ich modelliere das jetzt mal straight forward anhand deiner XML (siehe Bild im Anhang).
Die .ecore kann ich hier im Board nicht anhängen, daher habe ich sie umbenannt.

Die einzige Änderung die ich gemacht habe: Kunden haben nun eine Referenz auf ihre Transaktionen, nicht nur die Transaktion auf den Kunden.

Folgender Beispielcode:

```
import java.io.IOException;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;

import emfSample.EmfSampleFactory;
import emfSample.EmfSamplePackage;
import emfSample.Kassensystem;
import emfSample.Kunde;
import emfSample.Transaktion;
import emfSample.TransaktionsTyp;
import emfSample.Ware;
import emfSample.util.EmfSampleResourceImpl;


public class Main {

	private static EmfSampleFactory factory;
	
	public static void main(String[] args) throws IOException {
		Resource resource = new EmfSampleResourceImpl(URI.createFileURI("kasse.xml"));
		factory = EmfSamplePackage.eINSTANCE.getEmfSampleFactory();
		resource.getContents().add(createContents());
		resource.save(null);
	}

	private static Kassensystem createContents() {
		Kassensystem kasse = factory.createKassensystem();
		addKunden(kasse);
		addWaren(kasse);
		doATransaction(kasse);
		return kasse;
	}


	private static void addKunden(Kassensystem kasse) {
		Kunde sebiB90 = factory.createKunde();
		sebiB90.setGuthaben(500);
		sebiB90.setName("SebiB90");
		kasse.getKunden().add(sebiB90);
		
		Kunde wildcard = factory.createKunde();
		wildcard.setGuthaben(10000);
		wildcard.setName("Wildcard");
		kasse.getKunden().add(wildcard);
		
	}
	
	private static void addWaren(Kassensystem kasse) {
		Ware milch = factory.createWare();
		milch.setName("Milch");
		milch.setGuthaben(10);
		kasse.getWaren().add(milch);
		
		Ware kaffee = factory.createWare();
		kaffee.setName("Kaffee");
		kaffee.setGuthaben(15);
		kasse.getWaren().add(kaffee);
		
		
	}
	
	private static void doATransaction(Kassensystem kasse) {
		Transaktion transaction = factory.createTransaktion();
		Kunde sebiB90 = kasse.getKunden().get(0);
		transaction.setKunde(sebiB90);
		
		Ware kaffee = kasse.getWaren().get(1);
		transaction.setWare(kaffee);
		
		transaction.setTyp(TransaktionsTyp.KAUFEN);
		
		kasse.getTransaktionen().add(transaction);		
	}
}
```

Erzeugt folgende XML:
[XML]<?xml version="1.0" encoding="ASCII"?>
<Kassensystem xmlns="http://.java-forum.org/kassensysteme">
  <kunden name="SebiB90" guthaben="500" transaktionen="//@transaktionen.0"/>
  <kunden name="Wildcard" guthaben="10000"/>
  <transaktionen kunde="//@kunden.0" ware="//@waren.1"/>
  <waren name="Milch" guthaben="10"/>
  <waren name="Kaffee" guthaben="15" transaktionen="//@transaktionen.0"/>
</Kassensystem>[/XML]

Das ist übrigens nur eine Default Serialisierung. Bei Real-World Anwendungen würde man das Ecore Modell üblicherweise an ein Schema binden bzgw. das Ecore Modell direkt aus dem Schema erzeugen lassen.
Die Default XML Resource verwendet Pfadangaben für Referenzen sofern man EMF nicht mitgeteilt hat das man lieber IDs möchte (ein 3 Zeiler, aber es sollte ja nur ein einfaches Beispiel sein).

Einen extrem wichtigen Unterschied zu JaxB sieht man sofort wenn man die doATransactionMethode folgendermaßen ergänzt:


```
private static void doATransaction(Kassensystem kasse) {
		Transaktion transaction = factory.createTransaktion();
		Kunde sebiB90 = kasse.getKunden().get(0);
		transaction.setKunde(sebiB90);
		
		Ware kaffee = kasse.getWaren().get(1);
		transaction.setWare(kaffee);
		
		transaction.setTyp(TransaktionsTyp.KAUFEN);
		
		kasse.getTransaktionen().add(transaction);	
//man beachte das nirgends sebiB90.getTransactions().add(transaction) aufgerufen wurde!
		System.out.println(sebiB90.getTransaktionen().get(0).getWare().getName());
	}
```
Das syso liefert erstaunlicherweise trotzdem 'Kaffee'. Wie kann das sein?
Beim Modellieren habe ich Transaktion#kunde als eOpposite zu Kunde#transaktionen gesetzt, damit sind es gegensätzliche Referenzen. Füge ich beim Kunden in die Transaktionsliste eine neue Transaktion ein, wird dieser Transaktion automatisch das kunde Feld entsprechend gesetzt und umgekehrt. Das Modell hält sich immer konsistent und ist kein blöder JaxB Datencontainer.

Transaktionssicherheit würdest du zB mit EMF Transaction hinzufügen, ein mächtiges  Validierungsframework mit EMF Validation, OCL Support mir EMF OCL, Hibernate Anbindung mit EMF Teneo, Repository/DB Support mit EMF CDO oder SDO, flat file support mit xText, oder model to text, JCR Support mit JCR Management, Structural Diffs und Three Way Comparison mit EMF Compare, Queries auf Objektebene mit EMF Query und und und. 
Wie du siehst hat sich rund um EMF mittlerweile ein ganzes Ökosystem entwickelt, aber selbst in der reinen Core Funktionalität ist EMF JaxB um Meilen vorraus.
Strukturelle Integrität, der Code Generator kann händische Änderungen mergen, alle EMF Modelle haben vollen Observer und Behavioral Extension Support, EMF Modelle können vollständig reflexiv (ohne Code) verwendet werden, sind nicht an XML oder XMI gebunden, sind hoch effizient implementiert, beherrschen Cross References und automatische Proxy Resolution, und und und.
Da kommt man aus dem Schwärmen gar nicht mehr raus :autsch:


----------



## vodn7v (25. Jun 2009)

schau dir mal smooks an.


----------

