Hibernate-Designfrage zu Klassen

y0dA

Erfahrenes Mitglied
Hi!

Also ich bei mir für fast jede Tabelle ein Java Klassen äquivalent, nun meine Frage, "darf" ich jene Klassen nur in DAOS und Models benutzen oder auch bspw. in einem Controller --> bei Model-View-Controller Prinzip?`

Wenn ja, könne so eine Java Klasse, die eine Tabelle repräsentiert auch Objekte besitzen, welche in der Datenbank nicht existent sind sowie dürfen in jener Klasse auch Businesslogik für dieses Model reingeschrieben werden?

Im Moment habe ich es so, dass ich für jede Tabelle eine Java Klasse (nur mit getter/setter und constructor) und ein mapping file sowie eine dao Klasse habe. Mein Problem ist dass ich aber zu diesen Java Klassen auch "Businesslogik" brauche bzw Objekte, welche nicht in der DB existent sind bzw. weiß ich auch nicht ob ich diese Klassen "überall" benutzen darf (sauberes Design).
 
Dein DAO abstrahiert die Tabelle, deine Domänenklasse abstrahiert eine Zeile der Tabelle.

Grundsätzlich ist es ja so, dass das DAO Pattern (bzw. das Auslagern von Datenzugriffslogik in extra Klassen) u.a. dafür sorgen soll, dass die Domänenobjekte nichts von ihrer Persistierung wissen. Diese können (und - wenn man dem Domain Driven Design Ansatz folgt - sollten) auch mehr Logik als reine Getter / Setter haben.

Diese Objekte im Controller zu verwenden ist erst mal grundsätzlich legitim. Es ergibt sich ja folgende Dependencystruktur (DO = Domainobjects):

Code:
+-----------------------+----+
| Controller            |    |
+-----------------------+    |
| Servicelayer          | DO |
+-----------------------+    |
| DAO Layer             |    |
+-----------------------+----+

Dependencies wie folgt:
* Controller -> Servicelayer
* Servicelayer -> DAO Layer
* Controller -> DO
* Servicelayer -> DO
* DAO Layer -> DO

Das ist so die Standardarchitektur für Webanwendungen. Macht solang Sinn, wie der "Client" (also die Präsentationsschicht (Controller)) in der gleichen VM läuft, wie der Server (alles vom Servicelayer abwärts), da die Layer durch das gemeinsame Nutzen der DO recht stark aneinander gekoppelt sind. Problematisch kann es evtl auch werden, wenn man das LazyLoading von Hibernate nutzt, weil die Transaktion um den Servicelayer meist auch die Session schließt. Workaround hier der OpenSessionInViewFilter mit all seinen bekannten Nachteilen (bei Bedarf googlen).

Will man das vermeiden, lässt man den Servicelayer DTOs (Data Transfer Object) anstelle der DOs zurückgeben, was die Kopplung des "Clients" an den Server (Begriffsbedeutung wie grad eben geschildert) verringert, es allerdings nötig macht Extraklassen zu schreiben (DTOs).

Code:
+-----------------------+----+
| Controller            | DTO|
+=======================+====+
| Servicelayer          | DO |
+-----------------------+    |
| DAO Layer             |    |
+-----------------------+----+

Wald ein wenig gelichtet?

Gruß
Ollie
 
Du hast meinen Wald gelichtet, nur hast du mir nun weitere Wälder gezeigt..

Also ich benutze nur Hibernate (ohne Spring - ich weiß, schmerzt dich sicher :D - aber ich arbeite mich schon in Spring ein) und möchte eine schöne Abstraktion der DB Schicht machen.

Kannst du mir vllt. kurz erläutern wie ich hierbei vorgehen sollte?
Folgende Hibernate-DAO Präsentation habe ich schon gesichtet, verstehe ich aber nicht, da ich kein Bsp hierfür habe: http://www.hibernate.org/328.html

Reicht es eventuell dass ich für jede Hibernate Mapping Klasse (ja ich benutze auch keine Annotations) ein DAO Interface mache? Brauche ich auch sonst noch ein "Über"DAO-Interface?

mfg
 
Ja moooooment. Hier fiel kein einziges Wort über Spring. :) Architektur hat nicht in erster Linie mit Technolgie zu tun.

Grundsätzlich sollten Layer mit Interfaces versehen werden. D.h. du hast wahrscheinlich pro Domänenklasse ein DAO, dass aus Interface plus Implementierung besteht - eigentlich ganz genauso, wie in dem verlinkten Artikel beschrieben.

Sowas generisch zu implementieren (wie im Artikel versucht) ist sicher ein sinnvoller Ansatz wobei man allerdings nicht vergessen sollte, dass diese Implementierungen "nur" 80% der Fälle abdecken. Interessant ist es dabei, zu schauen, wie man diese generischen Implementierungen verwendet, wenn man manuell was dazu coden will. Im allgemeinen reicht einfaches Ableiten.

Beispiel? Okay, erster Fall - das generische DAO deckt die benötigte Funktionalität ab:

Java:
public class Person {
  // Deine Domainklasse
}

Java:
public interface PersonDAO extends GenericDAO<Person, Long> {
  // Interface kann leer bleiben, solang du keine zusäzliche Funnktionalität benötigst
}

Zusätzliche Funkntionalität deklarierst du nun einfach in deinem Interface und implementierst sie in einer Klasse, die von GenericHibernateDAO ableitet. Solang du keine zusätzliche Funktionalität hast, brauchst auch keine Extraimplementierung und kannst einfach Instanzen von GenericHibernateDAO.

Letzte offene Frage ist nun noch, wie deine Clientklassen (also die, die das DAO benutzen sollen) an ne Instanz kommen. Da bietet sich DependencyInjection (das Pattern, nicht gleich an Spring denken :D) an. Für welchen Container bzw. welche Implementierungsform davon man sich auch entscheidet.

Alternativ ginge eine Factory, mit all ihren bekannten Nachteilen (Abhängigkeit zur Implementierung, schlechte Testbarkeit usw.)

Gruß
Ollie
 
Hmm.. Ich dachte einfach daran dass jener Controller welcher ein Dao benötigt um auf die Werte zuzugreifen, einfach eine Instanz besitzt - nicht schön?

Wie ginge es denn mit Dependency Injection ohne Spring (höre eigentlich beides nur als Einheit).

mfg und schonmal Danke für den Crashkurs bisher :)
 
Hmm.. Ich dachte einfach daran dass jener Controller welcher ein Dao benötigt um auf die Werte zuzugreifen, einfach eine Instanz besitzt - nicht schön?

HM, und wie kommt der Controller an die? ;)

Wie ginge es denn mit Dependency Injection ohne Spring (höre eigentlich beides nur als Einheit).
DI ist ja mal in erster Linie ein Pattern. Verkürzt dargestellt besagt es nicht mehr, als das Instanzen von Abhängikeiten per Konstruktorparameter oder Setter Methode gesetzt werden und das Objekt, das die Abhängigkeit benötigt, diese NICHT selbst instantiiert bzw. holt.

Das führt dazu, dass man anstelle der "richtigen" Implementierung auch Mocks injecten kann - zum Unittesten zum Beispiel.

mfg und schonmal Danke für den Crashkurs bisher :)
Nix zu danken, gern geschehen.

Ollie
 
Das Model sollte die DAO Instanz nicht halten. Sonst würdest du ja (der Architektur oben nach) eine Dependency von DO nach DAO haben. Und das Domänenmodell sollte eigentlich nichts von Persistierung wissen.

Richtiger wäre es, der Controller hält die DAO Instanz und delegiert an sie.

Nochmal: wie kommt die Instanz zustande? Die in einem Klassenmember zu halten ist sicher richtig. Aber wer erzeugt die Instanz (des DAOs)?

(Die Antwort ist ganz einfach... ich will nur einfach, dass du merkst, dass man anfängt sich über Dependencies und die Konfiguration (wie wird was verdrahtet) Gedanken zu machen, wenn man über DI spricht)

Gruß
Ollie
 
Naja wenn du meinst dass der Controller die DAO Instanz besitzt, dann wird auch der Controller instanzieren? Und wenn ich dann ausm Controller das Model aufrufen soll ich die DAO übergeben oder wie? sry, stehe gerade am Schlauch bzw. hab ich mir über so etwas leider noch nie Gedanken gemacht ( bin aba am Weg der Besserung).
 
Ideal wäre es, wenn der Controller das DAO ebenfalls injiziert bekäme. Der Controller ruft doch auch nicht das Model. Er wird von der View benachrichtigt, ne Aktion auszuführen und reicht dann das Model an das DAO weiter.
 
Zurück