Lazy Loading bei Aggregaten (DDD)

Status
Nicht offen für weitere Antworten.

deamon

Bekanntes Mitglied
Inspiriert vom Domain Driven Design (DDD) habe ich eine Klasse, die als Aggregat Zugriff auf untergeordnete Objekte gibt. Um es etwas konkreter zu machen, habe ich eine Klasse "Benutzer", die eine Liste mit Objekten einer Untergeordneten Klasse enthält. Ein Benutzer-Objekt wird in einer HTTP-Session gespeichert.

Das Problem ist, dass die Liste wegen Lazy Loading nicht initialisiert ist und wenn man über das Benutzer-Objekt aus der Sitzung auf die Liste zugreift, bekommt man eine org.hibernate.LazyInitializationException. Um diese Exception zu vermeiden, möchte ich aber auch nicht beim Laden alles initialisieren und für jeden Benutzer ein fettes Objekt in der Session haben. Ich würde aber auch ungerne an meinem Benutzer-Objekt vorbei die untergeordneten Objekte direkt aus der DB holen, weil das gegen den Gedanken der Objektorientierung und DDD verstößt.

Hat jemand eine Idee, wie man (mit Hibernate) Lazy Loading von Aggreaten umsetzen kann?
 
S

SlaterB

Gast
du kannst ein Objekt später mit einer neuen Session verknüpfen, falls dir dieser Punkt noch fehlt,

ansonsten gibts in der Welt der Lebenden keine andere Wahl:
entweder du lädst die Daten vorher oder zum Zeitpunkt der Verwendung, was anderes ist theoretisch nicht möglich
 

deamon

Bekanntes Mitglied
Danke für deine Antwort. Dass ich ein Objekt später mit einer neuen Hibernate-Session verknüpfen kann, war mir bewusst, bloß weiß ich nicht, wie ich das in meinem konkreten Fall tun soll. Ich habe das Benutzer-Objekt in der HTTP-Session und will mir von diesem Benutzer-Objekt nun eine Liste mit untergeordneten Objekten ausgeben lassen. Die Hibernate-Session beginnt und endet in einer Methode des Repositorys. Das heißt, ich müsste eine extra Methode (oder einen entsprechenden Parameter) haben, die dafür sorgt, dass der Benutzer komplett initialisiert wird.

Oder sollte man die Hibernate-Session lieber an die HTTP-Session binden, so dass man überall Lazy Loading verwenden kann, sofern man die Objekte wieder an die Hibernate-Session gebunden hat? Irgendwie fürchte ich, dass der ganze Code dabei mit technischen Dingen durchzogen wird.
 
S

SlaterB

Gast
nein, keine Session in der Session ;)

wenn ein Servlet, oder wo immer du bist, irgendwas sinnvolles machen soll, dann bekommt das die DB-Session,
lädt alle nötigen Daten und schließt die Session, die Daten kommen in HTTP-Session und sind dann alle da,
ohne das irgendein JSP oder auch immer noch über LazyLoading nachdenken muss,

dass macht entweder genau das Servlet, welches eh DB-Zugriff hat, oder genau niemand
bis das nächste Servlet für den nächsten Client-Request sich darüber wieder den Kopf zerbrechen muss
 

byte

Top Contributor
Oder sollte man die Hibernate-Session lieber an die HTTP-Session binden, so dass man überall Lazy Loading verwenden kann, sofern man die Objekte wieder an die Hibernate-Session gebunden hat? Irgendwie fürchte ich, dass der ganze Code dabei mit technischen Dingen durchzogen wird.

Genau das ist eigentlich üblich und als Open-Session-In-View Pattern bekannt.

Du kannst Dir diese Funktionalität auch recht einfach wegkapseln, indem Du Dir einen Servlet-Filter schreibst. Der Filter öffnet vor dem Aufruf des Servlets die Hibernate Session und Transaktion. Am Ende macht der Filter dann den Commit. Die Session ist während des gesamten Requests geöffnet. Auf diese Weise bleibt Dein Code frei von diesen technischen Details.

Allerdings sollte Dir immer das n+1 Select Problem bekannt sein. Lazy Loading ist ne gute Sache. Wenn Du aber weisst, dass Du sowieso alle Daten brauchst, dann ist es von der Performance (fast*) immer besser, alle Daten per Fetch Join zu laden.



* "fast" deswegen, weil auch Joins irgendwann langsamer sein können. Dann macht es oft Sinn, mit Subselects zu arbeiten oder sogar mit mehreren Statements zu arbeiten. Der First Level Cache von Hibernate ist dabei ein wahrer Segen.
 
M

maki

Gast
DDD finde ich gut :)

Wie byto schon sagte, fetch joins wären ein Weg damit umzugehen, musst halt wissen für welche Use Cases welche Objekte im Graphen benutzt werden ;)
 

deamon

Bekanntes Mitglied
Open-Session-In-View-Pattern war genau das Stichwort nach dem ich gesucht hatte. Dazu gibt es auch eine lesenswerte Seite der Hibernate-Doku: https://www.hibernate.org/43.html

Jetzt muss ich mir nur noch überlegen, wie ich das möglichst elegant mit Wicket verbinde, ohne mit einem ServletFilter stumpf für jeden Request eine HibernateSession zu starten. Vielleicht muss ich doch mal mein Glück mit Spring (AOP) versuchen.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben