-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: TopThema LazyLoading
PostPosted: Tue Apr 11, 2006 2:08 pm 
Beginner
Beginner

Joined: Tue Mar 14, 2006 10:00 am
Posts: 22
Hibernate version:3.1

Hallo!
Ich bin wieder mal auf ein Problem gestossen, dass, so scheint es mir, doch viele beschäftigt. Ich will einer Collection eines Persistenten Objektes A ein Objekt B hinzufügen. Leider ist die Session schon geschlossen worden und das Objekt bereits persistiert worden. Also steht das Objekt im DETACHED Status. Beim Versuch die Collection zu erweitern kommt die oft gesehene, bestens bekannte und gefürchtete LazyInitializationException.

Nun hab ich versucht das Object A neu zu laden -> Fehlschlag (Objekt wird aus dem Cache geladen und es ändert sich nichts)

Dann hab ich versucht mit der statischen Funktion
Code:
Hibernate.initialize(objA)
bzw.
Code:
Hibernate.initialize(objA.getCollection())
das Objekt bzw. die Collection zu initialisieren, weil ich beim Debbugen draufgekommen bin, dass der Collection (PersistentSet) eine geschlossene Session zugewiesen ist. -> Fehlschlag; Nun kommt eine HibernateException mit der Meldung disconnected session.

Also wie kann ich einer Collection ein Objekt hinzufügen wenn dessen Session geschlossen ist, oder wie kann ich die Session wieder öffnen oder eine neue zuweisen???
Und ich will unbedingt LazyLoading verwenden!!!!

Also diesmal weis ich echt nix mehr wo ich nachlesen könnte.

HILFE!!!!! :-)

Tom


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 11, 2006 5:25 pm 
Regular
Regular

Joined: Mon Oct 06, 2003 7:17 am
Posts: 58
Location: Switzerland
1. Eine neue Session aufmachen.
2. Eine neue Transaktion starten.
3. Das neue Objekt B der Collection übergeben.
4. Auf der Session saveOrUpdate, mit dem Objekt A als Übergabeparameter, aufrufen.
5. Transaktion beenden
6. Session schliessen

Das sollte schon alles sein. Ansonsten musst du die Mapping Files und deinen Code posten.

Reto


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 2:13 am 
Beginner
Beginner

Joined: Tue Mar 14, 2006 10:00 am
Posts: 22
Danke Retro!

Ich habe das schon probiert! Vielleicht sollte ich dazusagen, dass ich auch mit Spring arbeite und so auf die Sessions bzw Transaktionen nur wenig programmatischen einfluss habe.
Ich habe aber schon versucht eine neue Session zu öffnen aber das hat nichts am Resultat geändert.

Code:
// auszug einer methode in einem DAO Klasse die Abgeleitet von HibernateDAOSupport ist
public void addAToB(A a, B b) {
  this.getHibernateTemplate().getSessionFactory().openSession();
  b.getAs().add(a);
  this.getHibernateTemplate().saveOrUpdate(b);
}


Beim Versuch auf die Collection (b.getAs()) zu zugreifen erhalte ich eine HibernateException mit der Meldung disconnected Session.

Wenn ich transiente ausprägungen der Objekte a, b habe dann funktioniert das ganze wunderbar (auch one das explizite öffnen der Session)

Hat da wer erfahrung in verbindung mit Spring (v1.2.6)??

tom


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 3:00 am 
Beginner
Beginner

Joined: Mon Dec 05, 2005 4:15 am
Posts: 36
tomSIEM wrote:
Danke Retro!

Ich habe das schon probiert! Vielleicht sollte ich dazusagen, dass ich auch mit Spring arbeite und so auf die Sessions bzw Transaktionen nur wenig programmatischen einfluss habe.
Ich habe aber schon versucht eine neue Session zu öffnen aber das hat nichts am Resultat geändert.

Code:
// auszug einer methode in einem DAO Klasse die Abgeleitet von HibernateDAOSupport ist
public void addAToB(A a, B b) {
  this.getHibernateTemplate().getSessionFactory().openSession();
  b.getAs().add(a);
  this.getHibernateTemplate().saveOrUpdate(b);
}


Beim Versuch auf die Collection (b.getAs()) zu zugreifen erhalte ich eine HibernateException mit der Meldung disconnected Session.

Wenn ich transiente ausprägungen der Objekte a, b habe dann funktioniert das ganze wunderbar (auch one das explizite öffnen der Session)

Hat da wer erfahrung in verbindung mit Spring (v1.2.6)??

tom


mit openSession() öffnest du zwar eine neue Session, diese Session benutzt du aber nicht weiter, stattdessen, sprichst du wieder das "detached" b-Objekt an.

Richtig wäre es:

Code:

public void addAToB(A a, B b) {
  Session s = this.getHibernateTemplate().getSessionFactory().openSession();
  B b1 = (B)s.get(B.class, b.getId());
  b1.getAs().add(a);
  s.saveOrUpdate(b1);
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 3:39 am 
Beginner
Beginner

Joined: Tue Mar 14, 2006 10:00 am
Posts: 22
Ahhhhhhhhhhhhhhhhh
Diese Eigenschaft habe ich beobachten können wusste aber nicht wie ich sie beheben könnte. Aber werden beim neu laden auch die sessions die der collection (PersistentSet) zugewiessen sind neu gesetzt???

also diese lösung funktioniert auch nicht
Code:
public void addAToB(A a, B b) {
    this.getHibernateTemplate().getSessionFactory().openSession();
    A na = (A)this.getHibernateTemplate().get(a.getClass(), a.getId());
    na.getAs().add(b);
    this.saveOrUpdate(na);
  }


bei diesem aufruf (na.getAs().add(b);) kommt es zu der bekannten LazyInitializeException (failed to lazily initialize a collection of role: A.bs)


tom


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 4:32 am 
Beginner
Beginner

Joined: Mon Dec 05, 2005 4:15 am
Posts: 36
tomSIEM wrote:
Ahhhhhhhhhhhhhhhhh
Diese Eigenschaft habe ich beobachten können wusste aber nicht wie ich sie beheben könnte. Aber werden beim neu laden auch die sessions die der collection (PersistentSet) zugewiessen sind neu gesetzt???

tom


Keinem detached Objekt ist eine Hibernate Session zugewiesen. Die Objekte wissen nichts über die Session, mit der die geladen wurden.

Die persistente Objekte sind mithilfe von CGLIB modifizierte Klassen, so dass zu den Getters und Setters die Datenbankzugriffe angehängt werden. Beim Detaching eines Objekts wird dir wieder ein normales POJO geliefert, ein Objekt mit den Werten. Und wenn irgendein Feld nicht gefüllt wurde, als das Objekt noch persistent war, bleibt das Feld leer, und beim Versuch auf diese Eigenschaft zuzugreifen, greifst du ins Leere. Also du braucht ein persistentes Objekt, aus welchem die Coll. geholt werden kann. Eine Möglichkeit ist der beschriebene Weg - ein persistentes Objekt mit dem selben ID wird geholt und mit diesem Obj. wird es weiter gearbeitet.
Es gibt noch weitere Wege, die Collection zu holen:
Du kannst das Objekt wieder persistent machen, und dann zur Collection ein Objekt hinzufügen, in diesem Fall aber werden alle andere Änderungen des Objekts gespeichert, was nich immer gewünscht ist. Und es gibt noch die Möglichkeit, über Hibernate.initialize(obj.getColl()) die benötigte Collection zu initialisieren - natürlich funktioniert dies wieder nur wenn das Objekt obj persistent ist.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 4:46 am 
Beginner
Beginner

Joined: Mon Dec 05, 2005 4:15 am
Posts: 36
tomSIEM wrote:

also diese lösung funktioniert auch nicht
Code:
public void addAToB(A a, B b) {
    this.getHibernateTemplate().getSessionFactory().openSession();
    A na = (A)this.getHibernateTemplate().get(a.getClass(), a.getId());
    na.getAs().add(b);
    this.saveOrUpdate(na);
  }


bei diesem aufruf (na.getAs().add(b);) kommt es zu der bekannten LazyInitializeException (failed to lazily initialize a collection of role: A.bs)


tom


Dieser Code:

Code:
    A na = (A)this.getHibernateTemplate().get(a.getClass(), a.getId());


öffnet implizit eine neue Session, holt ein Objekt na , schließt wieder die Session, und gibt das detached Objekt zurück. und die Sitzung, die eine Zeile davor geöffnet wird, wird nie mehr benutzt.

dieser Code soll funktionieren:

Code:
public void addAToB(A a, B b) {
    Session s = this.getHibernateTemplate().getSessionFactory().openSession();
    A na = s.get(a.getClass(), a.getId());
    na.getAs().add(b);
    s.saveOrUpdate(na);
  }


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 5:21 am 
Beginner
Beginner

Joined: Tue Mar 14, 2006 10:00 am
Posts: 22
Code:
public void addTestItemToTestStructure(TestStructure ts, TestItem ti) {
    this.getHibernateTemplate().getSessionFactory().openSession();
    TestItem nti = (TestItem)this.getHibernateTemplate().load(ti.getClass(), ti.getId());
    this.getHibernateTemplate().initialize(nti.getTestStructures());
    nti.getTestStructures().add(ts);
    this.saveOrUpdate(ti);
  }


also dieser code wirft
LazyInitializationException: could not initialize proxy - the owning Session was closed
wenn nti.getTestStructures().add(ts); aufgerufen wird

auch wenn ich die Collection nicht mit initialize bearbeite :-)

also liegt es jetzt daran, dass das object nicht persistent ist???
also nti ist nach meinem verständnis nach transient ( hat keine definierte id)

ich kenn mi nimmer aus :-)

tom


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 12, 2006 5:33 am 
Beginner
Beginner

Joined: Tue Mar 14, 2006 10:00 am
Posts: 22
sw79

you are my hero!!!!

problem gefixt ---> neues problem wartet schon

danke für die hilfe!
ich hab da anscheinend was überlesen in deinen postings

tom


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 20, 2006 11:26 am 
Senior
Senior

Joined: Mon Aug 22, 2005 5:45 am
Posts: 146
sw79 wrote:
tomSIEM wrote:

Dieser Code:

Code:
    A na = (A)this.getHibernateTemplate().get(a.getClass(), a.getId());


öffnet implizit eine neue Session, holt ein Objekt na , schließt wieder die Session, und gibt das detached Objekt zurück. und die Sitzung, die eine Zeile davor geöffnet wird, wird nie mehr benutzt.

dieser Code soll funktionieren:

Code:
public void addAToB(A a, B b) {
    Session s = this.getHibernateTemplate().getSessionFactory().openSession();
    A na = s.get(a.getClass(), a.getId());
    na.getAs().add(b);
    s.saveOrUpdate(na);
  }


hm, da würde ich mal Einhaken wollen.
Wenn man eine webapp als client hat und den Spring OpenSessionInView-Filter verwendet, dann lautet das Konzept bekanntermassen, dass die hibernate-session über den _gesamten_ request-Zyklus geöffnet bleiben soll.
D. h. in einer action (struts, WebMVC oder was auch immer) sollte man sich via sessionFactory.getCurrentSession() die _aktuelle_ session besorgen und darauf Transaktionen wie die in dem code snippet durchführen.

Es ist also (zumindest unter diesen Voraussetzung) völlig unnötig mit unterschiedlichen sessions zu arbeiten.
1 HttpRequest == 1 hibernate-session!
--> keine detached objects

_________________
Please don't forget to give credit, if my posting helped to solve your problem.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 22, 2006 9:01 am 
Beginner
Beginner

Joined: Tue Mar 14, 2006 10:00 am
Posts: 22
im prinzip hast du recht

aber man soll die sessions nur solange geöffnet halten wie unbedingt notwendig:
- ressourcenfresser
- weil sessions einen undefinierten zustand einnehmen wenn mal was schief geht

tom


Top
 Profile  
 
 Post subject: Sessions und Lazy-Exceptions
PostPosted: Tue Dec 26, 2006 11:52 am 
Beginner
Beginner

Joined: Sat Dec 09, 2006 12:02 pm
Posts: 26
Dieser Thread sieht eigentlich so aus, als könnte er mir helfen, aber da ich sehr neu in der Spring und hibernate-Welt bin klappt das wohl noch nicht so ganz.

Dieses dumme Lazy-Load-Problem scheint ja echt wirklich jeder zu haben.

Im Code stand sowas drin wie

1. Hole die aktuelle Session
2. Sag der Session, welches Objekct du brauchst
3. Caste das was da zurückkommt, egal was es ist, einfach in dein Objekt und schwupps gehts...

Da ich usprünglich mal C# programmiert habe, macht das für mich keinen sinn. Ich will doch einfach nur ein Objekt laden, welches ein anderes Objekt enthält, welches durch die Foreign-Keys der hbm.xml-Dateien spezifiziert ist... Das kann doch nicht so schwer sein.

Nochwas, ich versuche dieses Problem nun schon seit zwei Tagen zu lösen und auch wenn ich schon viele Foren gelesen habe, irgendeiner schlägt dann doch immer ne andere Lösung vor. Lazy einfach auf false setzen möcht ich nicht, da ja sonst immer echt alles geladen wird. erst wenn ich drauf zugreife soll das geschehen. (Nebenbeigesagt, ich habs mal probiert in meine hbm.xml-Dateien lazy = "false" reinzuschreiben und er hat immer gesagt, lazy ist nicht definiert).

Wäre echt schön, wenn mir das mal einer ordentlich erklären könnte. Ich benutze hibernate 3 und eclipse.

ich versuche eine jsp-oberfläche zu bauen, wo mittels Tags die Daten an die Oberfläche gelangen. Ich hab auch gelesen, dass es so ein OpenSessionInViewFilter objekt gibt.. Aber der Typ, der das da erklärt hatte, hat erstmal 20 Seiten Quelltext geschrieben und dann gesagt, so, nun sind die Vorbereitungen abgeschlossen.. Da hab ich das gleich sein lassen...


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.