tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
5
ZUGRIFFE
1083
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    DarthShader DarthShader ist offline Mitglied Platin
    Registriert seit
    May 2004
    Beiträge
    684
    Hallo zusammen,

    ich möchte ein Objekt via Hibernate aus der Datenbank laden und es nach Schließen der Session verwenden. Ich weiß um den Mechanismus mit der Instrumentation und dem Lazy Loading, sodass das Objekt nach und nach die gewünschten Properties bei Zugriff nachlädt.

    Nun dachte ich jedoch, dass das Flushen und/oder Schließen der Session bewirkt, dass das Objekt vollständig geladen wird, dies scheint aber nicht der Fall zu sein.

    Hier ein kleines Beispiel:

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
     
    Plane plane = new Plane();
    plane.setName( "Ein Flugzeug" );
    session.save( plane );
     
    transaction.commit(); // (1)
    session.close(); // (2)
     
    session = sessionFactory.openSession(); // (3)
    transaction = session.beginTransaction(); // (4)
     
    Plane loadedPlane = (Plane)session.load( Plane.class, plane.getId() );
     
    session.clear(); // (5)
    session.flush(); // (6)
     
    transaction.commit();
    session.close();
    sessionFactory.close();
     
    System.out.println();

    Führe ich das aus, wirft er eine

    Code java:
    1
    
    org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    Exception - was ja auch verständlich ist, denn ich greife ja auf das Objekt, welches noch nicht vollständig geladen ist, zu, obwohl die Session geschlossen ist. Allerdings dachte ich, dass wegen (5) und/oder (6) das Objekt vollständig geladen wird. Denn was macht es für einen Sinn, noch nicht vollständig geladene Objekte (attached) zu haben, jedoch eine geschlossene Session?

    Ich kenne nur einen "Workaround", um das zu umgehen (bzw. das Objekt zu "detachen"): man cloned es, z.B. mit "Dozer".
    1. Etwas, was ich nicht begreife ist, warum mit (1) bis (4) eine Exception geworfen wird. Nehme ich diese Zeilen nämlich raus, so wird keine Exception geworfen - kann mir das jemand erklären?
    2. Gibt es einen anderen Weg, um das Objekt vollständig zu laden, wenn die Session geschlossen wird (ja, ich möchte Lazy Loading ansonsten aktiviert lassen)?


    Über Eure Hilfe würde ich mich sehr freuen


    Vielen Dank!
     

  2. #2
    Avatar von Sentoo
    Sentoo Sentoo ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Brühl
    Beiträge
    131
    Hi,

    füg doch in der Zeile unter dem laden ein
    Code java:
    1
    2
    
    Plane loadedPlane = (Plane)session.load( Plane.class, plane.getId() );
    loadedPlane.getTheLazyAttribute(); // lade das Attribut das lazy ist

    Wie soll das sonst funktionieren? Deine Idee das bei einem Flush automatisch alle Attribute mit Lazy nachgeladen werden ist rechter Wahnsinn. Warum?

    Denk mal nach, warum Lazy sinn macht, genau, weil Du unter Umständen anderenfalls die gesamte Datenbank in den Speicher lädst. Mit lazy schiebst Du einen Riegel davor.

    Würdest Du jetzt beim flush extra ALLE Attribute laden, die mit lazy markiert sind, würdest Du auch ALLE Attribute verbundener Entities laden und so sehr wahrscheinlich die komplette Datenbank in den Speicher laden.

    Finde schon gut, dass dein Beispiel so funkioniert, wie es das macht ...
     

  3. #3
    DarthShader DarthShader ist offline Mitglied Platin
    Registriert seit
    May 2004
    Beiträge
    684
    Hallo Sentoo,

    Zitat Zitat von Sentoo Beitrag anzeigen
    Hi,

    füg doch in der Zeile unter dem laden ein
    Code java:
    1
    2
    
    Plane loadedPlane = (Plane)session.load( Plane.class, plane.getId() );
    loadedPlane.getTheLazyAttribute(); // lade das Attribut das lazy ist
    Da hinkt natürlich das Beispiel, denn in meinem echten Domain Modell müsste man da "etwas mehr" manuell aufrufen. Aber das ist auch gar nicht so recht das Thema, mir ist natürlich klar, was Lazy Laoding ist, wozu es gut ist, und dass man die Sache umgehen könnte, wenn man explizit alle Properties "anfordert".

    Zitat Zitat von Sentoo Beitrag anzeigen
    Wie soll das sonst funktionieren? Deine Idee das bei einem Flush automatisch alle Attribute mit Lazy nachgeladen werden ist rechter Wahnsinn. Warum?
    Ich gehe mal davon aus, dass Du das mit dem Wahnsinn nicht so gemeint hast

    Zitat Zitat von Sentoo Beitrag anzeigen
    Denk mal nach, warum Lazy sinn macht
    Wie schon gesagt, mir ist klar, wofür es da ist.

    Ich denke, mein Anliegen zielt eher auf das allgemeine Thema des Detaching von Persistent Entities hinaus - und die Idee das mit "flush" oder "close" der Session zu verbinden, kommt daher, da ich mir dachte, man könne während einer offenen Session mit dem Entity normal arbeiten und dabei alle Vorzöge des Lazy Loading genießen. Beim Schließen könnte ich mir dann vorstellen, dass das Objekt automatisch detached wird (wobei ich mit "detachen" meine, dass die Proxys entfernt werden und das Objekt komplett geladen wird).

    Denn wenn man die Session schließt, kann man mit einem Objekt zurückbleiben, welches eine Exception werfen kann, nur weil man auf ein Property zugreift. Das kann man leicht übersehen und das Verhalten wird nach außen hin nicht klar dargestellt - man muss es eben wissen.

    Dem Design nach scheint es also besser zu sein, beim Schließen der Session mit einem Objekt zurück zu bleiben, das leicht eine Exception werfen kann, als sicher zu stellen, dass dieses "komplett" ist (wie gesagt, man kann die Vorzüge von Lazy Loading ja nutzen, während die Session noch offen ist).

    Noch bleibt es für mich eine Design-Entscheidung, ich habe für mich noch nicht das überzeugende pro/contra Argument gefunden.
     

  4. #4
    minjaman minjaman ist offline Rookie
    Registriert seit
    Nov 2010
    Beiträge
    6
    Hallo DarthShader,

    Hast Du es schon einmal mit Gilead versucht?
    http://noon.gilead.free.fr/gilead/

    Gruß
     

  5. #5
    DarthShader DarthShader ist offline Mitglied Platin
    Registriert seit
    May 2004
    Beiträge
    684
    Hallo minjaman,

    nein, Gilead kannte ich bisher noch nicht. Klingt aber interessant, vielen Dank für den Link.

    Bisher habe ich immer mit Dozer gearbeitet. Die Kombination mit Hibernate und Dozer klappte sehr gut, vor allem um die von Hibernate verwendeten Proxy Klassen los zu werden, wenn man das Persistent Entity z.B. via RMI an ein entferntes System schickt, oder eben auch, um GWT-Kompatible Klassen zu verwenden (wird ja auch auf der Gilead Seite erwähnt wie ich gesehen habe).
     

  6. #6
    sebastianb sebastianb ist offline Mitglied Gold
    Registriert seit
    Dec 2009
    Beiträge
    125
    Mal abgesehen von diversen Lösungsansätzen (z.B. mit AspectJ) zum dynamischen Nachladen von nicht initalisierten Objekten bietet z.B. OpenJPA das definieren sogenannter Fetch-Groups. Mit Hilfe dieser ist es möglich beim Laden einer Entity zu definieren, welche Beziehungen mitgeladen werden sollen und welche nicht.
    Ein etwas unschöner Workaround ist außerdem, dass du beim Laden der Entity die gewünschten Beziehungen über den Getter aufrufst und dann zB bei Collections size() oder hashcode() aufrufst, was dann Hibernate dazu veranlasst die Beziehungen mitzuladen.

    Gruß

    Sebastian
     

Ähnliche Themen

  1. Antworten: 73
    Letzter Beitrag: 19.04.08, 22:03
  2. Abstand wenn formular geschlossen wird
    Von webpagemaster im Forum CSS
    Antworten: 3
    Letzter Beitrag: 24.06.06, 10:35
  3. Antworten: 3
    Letzter Beitrag: 06.10.05, 23:21
  4. PopUp, wenn Fenster geschlossen wird
    Von Eiszwerg im Forum Javascript & Ajax
    Antworten: 13
    Letzter Beitrag: 18.06.05, 22:40
  5. Neu laden wenn Popup geschlossen wird
    Von sanches im Forum Javascript & Ajax
    Antworten: 1
    Letzter Beitrag: 12.02.05, 22:47