# Verständnisproblem mit mehreren DAOs



## SebiB90 (7. Apr 2009)

Hi,

ich arbeite momentan an einem kleinen Kassensystem und ich habe Probleme bei der Speicherung meiner Objekte bzw. wo welches Object gespeichert werden soll. Ich hoffe, ich bin jetzt mit meiner Frage im richtigen Forum, da die Speicherung noch nicht festgelegt ist(sowohl eine datenbank als auch xml kommt in frage).

Also erstmal meine Ausgangssituation:
Ich habe eine Klasse Kunde und eine Klasse Transaktion, die in eine 1:n Beziehung haben. Mal paar Ausschnitte:
[HIGHLIGHT="Java"]public class Kunde {
  private String name;
  private int guthaben;
  private ArrayList<Transaktion> transaktionen;
  //restlicher code
}
[/HIGHLIGHT]
[HIGHLIGHT="Java"]public class Transaktion {
  private TransaktionType type;
  private Kunde kunde;
  private int betrag;
  //restlicher code
}
[/HIGHLIGHT]
Also habe ich eine Klasse Kunde mit Namen, seinem Guthaben(ist so ein 'Prepaidsystem') und seinen Transaktionen. In der Transaktion gibt eine Referenz auf den Kunden, den Typ(z.b. Guthaben einzahlen etc.) und dem Betrag(z.b. wie viel eingezahlt wird).

Die Transaktionen werden von einer anderen Klasse ausgeführt. Ich will das jetzt so machen, dass sobald eine Transaktion ausgeführt wird, sie auch gespeichert wird. Für die Speicherung habe ich mir Interfaces geschrieben(KundenDAO, TransaktionDAO), die mir CRUD Operationen bereit stellen.
Jetzt sieht die Ausführung einer Einzahlen Transaktion in etwa so aus:
[HIGHLIGHT="Java"]
Kunde kunde = transaktion.getKunde();
int betrag = transaktion.getBetrag();
int kundenGuthaben = kunde.getGuthaben();
kunde.setGuthaben(kundenGuthaben + betrag);
transaktion.setDone(true);
transaktion.setExecuteTime(new Date());
this.transaktionenDAO.save(transaktion); // hier die Speicherung
[/HIGHLIGHT] 

Um jetzt zu meiner eigentlichen Frage zu kommen. Sollte die save Methode des TransaktionDAO auch den Kunden mitspeichern oder sollte ich noch einen Aufruf machen kundenDAO.save(kunde) ?
Wie würdet ihr es machen? bzw. wie würde es Hibernate machen, wenn ich sagen würde, dass er die Transaktion speichern soll?

Weiß jetzt nicht, wie ich das lösen soll. Einerseits ist das TransaktionDAO nicht für den Kunden zuständig, andererseits muss das TransaktionDAO beim laden einer Transaktion auch den Kunden mitladen, also wieso dann nicht auch mitspeichern?

Mfg
SebiB90


----------



## maki (7. Apr 2009)

Sieh es mal so:
Bevor die Transaktion gespeichert werden kann, muss doch der Kunde bereits existieren.
Du kannst Hibernate sagen das es sich darum kümmern soll, aber die wichtige Frage ist erstmal eine andere...

Die imho entscheidende Fragen:
Von wem soll der Kunde und die Transaktion gespeichert werden?
Wie sind diese Objekte Assoziiert?

Im Prinzip gibt es 2 Möglichkeiten
1. "Transaktion Script" - P of EAA: Transaction Script
Sehr üblich, wenn auch etwas "prozedural", wird unübersichtlich wenn es sich um komplexe Businesslogik handelt.
Man trifft hierbei oft auf den Begriff "Manager" o. ä., "dumme" POJOs die nicht viel mehr Logik haben als Getter & Setter für alle Properties sind ein eindeutiges zeichen dafür, die eigentliche Logik steht mehr oder weniger komplett in der Methode eines Managers/EJB SessionBean, welche alle notwendigen DAOs aufruft und damit die POJOs verarbeitet.
2. "Domain Modell" - P of EAA: Domain Model
Aufwändiger und nicht so häufig verwendet, dafür die bessere Wahl bei komplexer Businesslogik, "echtes" OO Design, die Businesslogik ist über mehrere Klassen verteilt, POJOs können selbst (über Repositories) andere POJOs speichern/finden.

Hibernate kannst du über das cascade Attribut sagen wann welche assozierten Objekte gespeichert werden sollen, aber die Assoziationen selbst musst du dir schon überlegen


----------



## SebiB90 (8. Apr 2009)

Also zunächst: Der Kunde existiert immer bereits und ist gespeichert bevor eine Transaktion mit ihm ausgeführt werden kann.

Ich versteh nicht ganz deine Frage mit wie diese Objekte assoziiert sind. Ich sagte doch, dass es eine 1:n assoziation ist. Ein Kunde hat 0 bis * Transaktionen und jede Transaktion hat immer 1 Kunden.

Wenn ich die 2 Varianten richtig verstanden habe, müsste ich ein Transaktion Script haben. Die Klasse Kunde und Transaktion sind nur Beans, die die Informationen speichern. Die eigentliche BuisnessLogic findet in Serviceklassen statt. Also z.b. KundenService zum erstellen/bearbeiten/löschen der Kunden und TransaktionSerivce zum ausführen der Transaktionen.

Meine eigentliche Frage war/ist jetzt aber, wie man es handhaben soll mit der Speicherung. Sollte das TransaktionDAO den veränderten Kunden mit abspeichern oder sollte der TransaktionService den Kunden durch ein aufruf der save Methode des KundenDAOs speichern. Was wäre da üblich? Gibts da irgendwelche 'Richtlinien', wie man es machen sollte? Oder macht das jeder Entwickler wie es ihm passt?


----------



## byte (8. Apr 2009)

Ich habe noch nicht davon gehört, dass es irgendwelche Best Practices bei Kaskadierung gibt. Das muss man von Fall zu Fall entscheiden. Vorsichtig wäre ich immer bei Kaskadiertem DELETE. Das schließe ich meistens aus, um nicht versehentlich Datensätze zu löschen.


----------



## maki (8. Apr 2009)

> Wenn ich die 2 Varianten richtig verstanden habe, müsste ich ein Transaktion Script haben.


Ja.



> Meine eigentliche Frage war/ist jetzt aber, wie man es handhaben soll mit der Speicherung. Sollte das TransaktionDAO den veränderten Kunden mit abspeichern oder sollte der TransaktionService den Kunden durch ein aufruf der save Methode des KundenDAOs speichern.


Da du uns die Mapping Infos vorenthälst kann ich dir nicht sagen, welche die sog. "owning"  Seite ist, also die,  welche die Assoziation wirklich speichert.

*Eigentlich* brauchst du gar keine DAOs selbst aufzurufen wenn alle Änderungen innerhalb einer Session gemacht werden, dann würde Hibernate das automatisch anhand der Mapping Infos machen.


----------



## SebiB90 (8. Apr 2009)

maki hat gesagt.:


> Da du uns die Mapping Infos vorenthälst kann ich dir nicht sagen, welche die sog. "owning"  Seite ist, also die,  welche die Assoziation wirklich speichert.
> 
> *Eigentlich* brauchst du gar keine DAOs selbst aufzurufen wenn alle Änderungen innerhalb einer Session gemacht werden, dann würde Hibernate das automatisch anhand der Mapping Infos machen.



Ich versteh dich wohl nicht ganz, da ich mich mit Hibernate bisher eher nicht auskenne. Wie schon im ersten Post gesagt, ist die Implementierung der DAOs noch nicht festgelegt. Es soll sowohl eine XML als auch eine Datenbank implementierung geben.

Aber vllt könnte das sein, was du meinst: Es ist so gedacht, dass die Transaktion die ID des Kunden abspeichert. Also das die Transaktion den Fremdschlüssel hat. Beim laden des Kunden werden alle Transaktionen mitgeladen bei denen die Kunden ID übereinstimmt.


----------



## byte (8. Apr 2009)

Ich verstehe deine Frage offenbar nicht. Du wolltest doch wissen, wie sowas bei Hibernate geregelt ist!? Darauf hab ich mich bezogen. Dort kannst Du im Mapping einer Assoziation angeben, wie die Kaskadierung aussehen soll (cascade Attribut). Da gibts verschiedene Kaskadierungstypen, z.B. SAVE, DELETE, REFRESH usw. Kaskadierung bedeutet in diesem Zusammenhang einfach, dass die jeweiligen Methoden der Session (save(), delete(), refresh() usw.) zur referenzierten Entität weitergeschleift werden.


----------



## SebiB90 (8. Apr 2009)

byto hat gesagt.:


> Ich verstehe deine Frage offenbar nicht. Du wolltest doch wissen, wie sowas bei Hibernate geregelt ist!?



Jein. Also auch. Ich wollte wissen wie man sowas allgemein regelt und dazu wollte ich wissen wie es Hibernate macht, da es sozusagen eine "Autorität" in dem Gebiet ist. Aber wie du schriebst, gibt es anscheind keine Best Practise bei Kaskadierung. Das war meine eigentlich Frage, nur umständlich beschrieben. Danke für die Antwort 

Der letzte Post war jetzt auf maki bezogen um ihm mein Sachverhalt besser zu erklären. Das ich ihm schlecht die Hibernate Mapping Infos geben kann, wenn das noch gar nicht verwendet wird


----------

