-->
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.  [ 9 posts ] 
Author Message
 Post subject: Lazy Fetching
PostPosted: Fri Oct 28, 2005 7:39 am 
Newbie

Joined: Thu Oct 27, 2005 7:51 am
Posts: 9
Location: Germany
Hallo,

ich habe eine Frage zum lazy fetching.
Ich habe eine Containerklasse, die quasi die Objecte der Datenbank zwischenspcihert, damit nicht immer eine DB gamacht werden muss.

Die Person oder eine Subclass davon hat auch one-to-many oder many-to-many assoziationen.

Mit der Doku bin ich schonmal soweit gekommen, dass Hibernate mittels lazy associations arbeitet.

Also wenn ich Alle Personen lese werden nicht alle assoziatinsobjekte gelesen.

Wenn ich aber nun die Objeke in einem JTree darstellen will, dann werden die anderen Assoziationen z. T. ja erst gelesen, wenn die session schon geschlossen ist. (Deswegen ja auch die Exception)

Gibt es denn noch andere Möglichkeiten, ausser die Fetch-Strategie umzustellen, dass man alle Objekte zusammen ausliest.

Weil wenn ich die fetch strategie umstelle, dann habe ich ja IMME alle Objekte im Speicher und nicht nur dann, wenn ich sie brauche.

Ich hoffe man kann mein problem verstehen.
Und ich hoffe noch mehr, dass man mir helfen kann :-)

Nun noch ein paar Files, die zu dem problem führen.

Hibernate version: 3

Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

        <class name="name.pawlitzki.kita.objects.person.Person" table="PERSONS">
                <id name="id" column="person_id" type="long">
                        <generator class="identity"/>                       
                </id>
                <property name="birthday" type="date"/>
                <property name="gender"/>
               
                <one-to-one
                   name="name"
                   class="name.pawlitzki.kita.objects.person.Name"
                   constrained="true"
                   cascade="all" />

                <many-to-one
                 name="religion"
                 column="religion_id"
                 class="name.pawlitzki.kita.objects.person.Religion"
                 update="true"
                 insert="true"
                 cascade="all"/>
                 
              <many-to-one
                 name="address"
                 column="address_id"
                 class="name.pawlitzki.kita.objects.person.Address"
                 update="true"
                 insert="true"
                 cascade="all"/>

            <!-- BEGIN Parent -->
                <joined-subclass name="name.pawlitzki.kita.objects.person.Parent" table="PARENTS">
                 <key column="person_id"/>
                 
                 <property name="occupation"/>
                 
                 <set name="contacts" table="PARENTS_CONTACTS" cascade="all">
                        <key column="person_id"/>
                        <many-to-many
                                column="contact_id"
                                class="name.pawlitzki.kita.objects.person.Contact"/>
                   </set>
                                     
                   <set name="relations" cascade="all">                
                   <key column="person_id"/>
                   <one-to-many class="name.pawlitzki.kita.objects.person.Relation"/>
               </set>               
            </joined-subclass>             
            <!-- END Parent -->   

            <!-- BEGIN NurseryPerson -->
                <joined-subclass name="name.pawlitzki.kita.objects.person.NurseryPerson" table="NURSERY_PERSONS">
                 <key column="person_id"/>

                 <property name="fromDate" type="date"/>
               <property name="untilDate" type="date"/>
                 <set name="absencePeriods">
                    <key column="person_id"/>
                    <one-to-many class="name.pawlitzki.kita.objects.person.AbsencePeriod"/>
                 </set>
                 
                 <!-- BEGIN Child -->
                 <joined-subclass name="name.pawlitzki.kita.objects.person.Child" table="CHILDS">
                    <key column="person_id"/>
                    
                    <many-to-one
                       name="group"
                       column="group_id"
                       class="name.pawlitzki.kita.objects.person.Group"/>                    
                    
                  <set name="relations">
                         <key column="person_id"/>
                         <one-to-many class="name.pawlitzki.kita.objects.person.Relation"/>
                   </set>
                 </joined-subclass>
                 <!-- END Child -->
                 
                 <!-- BEGIN Employee -->
                 <joined-subclass name="name.pawlitzki.kita.objects.person.Employee" table="EMPLOYEES">
                    <key column="person_id"/>
                    
                    <property name="leaveDays"/>
                    <property name="role"/>
                    
                    <set name="groupFunctions">
                           <key column="person_id"/>
                           <one-to-many class="name.pawlitzki.kita.objects.person.GroupFunction"/>
                  </set>
                    
                 </joined-subclass>
                 <!-- END Employee -->
            </joined-subclass>
            <!-- BEGIN NurseryPerson -->

        </class>
</hibernate-mapping>


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

        <class name="name.pawlitzki.kita.objects.person.AbsencePeriod" table="ABSENCE_PERIODS">
                <id name="id" column="id" type="long">
                        <generator class="identity"/>
                </id>
                <property name="fromDate" type="date"/>
            <property name="untilDate" type="date"/>
                <property name="reason"/>

               <many-to-one
                     name="nurseryPerson"
                     column="nursery_person_id"
                  class="name.pawlitzki.kita.objects.person.NurseryPerson"/>

        </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Code:
private void refresh() {
      Session session = HibernateUtil.currentSession();
      Transaction tx = session.beginTransaction();
      
      List persons = session.createQuery("from Person").list();
      
      tx.commit();
      HibernateUtil.closeSession();
      
      boolean added = this.persons.addAll(persons);
      if (added) {
         setChanged();
         notifyObservers();
      }
      
      
   }

Full stack trace of any exception that occurs:
Quote:
Hibernate: select person0_.person_id as person1_0_, person0_.birthday as birthday0_, person0_.gender as gender0_, person0_.religion_id as religion4_0_, person0_.address_id as address5_0_, person0_1_.occupation as occupation1_, person0_2_.fromDate as fromDate3_, person0_2_.untilDate as untilDate3_, person0_3_.group_id as group2_4_, person0_4_.leaveDays as leaveDays5_, person0_4_.role as role5_, case when person0_3_.person_id is not null then 3 when person0_4_.person_id is not null then 4 when person0_1_.person_id is not null then 1 when person0_2_.person_id is not null then 2 when person0_.person_id is not null then 0 end as clazz_ from PERSONS person0_ left outer join PARENTS person0_1_ on person0_.person_id=person0_1_.person_id left outer join NURSERY_PERSONS person0_2_ on person0_.person_id=person0_2_.person_id left outer join CHILDS person0_3_ on person0_.person_id=person0_3_.person_id left outer join EMPLOYEES person0_4_ on person0_.person_id=person0_4_.person_id
2005-10-28 13:29:41,888 [AWT-EventQueue-0] ERROR (LazyInitializationException.java:19) - failed to lazily initialize a collection of role: name.pawlitzki.kita.objects.person.NurseryPerson.absencePeriods, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: name.pawlitzki.kita.objects.person.NurseryPerson.absencePeriods, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:138)
at name.pawlitzki.kita.gui.tree.NurseryPersonTreeNode.<init>(NurseryPersonTreeNode.java:20)
at name.pawlitzki.kita.gui.tree.ChildTreeNode.<init>(ChildTreeNode.java:22)
at name.pawlitzki.kita.gui.ChildrenTreeInternalFrame.addChild(ChildrenTreeInternalFrame.java:120)
at name.pawlitzki.kita.gui.ChildrenTreeInternalFrame.readChildren(ChildrenTreeInternalFrame.java:104)
at name.pawlitzki.kita.gui.ChildrenTreeInternalFrame.<init>(ChildrenTreeInternalFrame.java:81)
at name.pawlitzki.kita.gui.KITAMainFrame$MenuBarActionListener.actionPerformed(KITAMainFrame.java:148)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.AbstractButton.doClick(AbstractButton.java:302)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1000)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:1041)
at java.awt.Component.processMouseEvent(Component.java:5488)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3126)
at java.awt.Component.processEvent(Component.java:5253)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1774)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 28, 2005 9:17 am 
Beginner
Beginner

Joined: Mon Oct 24, 2005 9:46 am
Posts: 22
Location: Germany
ohne mich wirklich in deinen Code reingelesen zu haben:

Versuch doch mal die Session erst nachdem du mit der Collection hantiert hast zu schliessen.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 28, 2005 3:14 pm 
Newbie

Joined: Thu Oct 27, 2005 7:51 am
Posts: 9
Location: Germany
das ist schwierig bis unmöglich. Das gnaze spielt isch nämlich in 2 klassen hab. Einmal dem JTree(Model) und dem PersonFolder, welcher den Zwischenspeicher darstellt.

Ich habe die Einzelnen elemente in einem JTree.
Jeder Koten stellt ein Objekte dar. Unterknoten sind die Objekte die assoziert werden.

Und ich kann ja nich wissen, wann welcher unterknoten aufgeblendet wird. udn damit also nicht, wann ich welches assozierte Objekt brauche.

Ich müsste die session also so lange auf haben, bis sich das Fenster, in dem der Jtree drin ist, schliesse


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 29, 2005 2:45 am 
Regular
Regular

Joined: Tue May 24, 2005 9:06 am
Posts: 64
Du solltest *innerhalb* einer Transaktion einen FETCH-Join machen. Vorsicht: der liefert aber Duplikate, auch wenn man SELECT DISTINCT verwendet.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 02, 2005 4:10 am 
Newbie

Joined: Thu Oct 27, 2005 7:51 am
Posts: 9
Location: Germany
OK, das scheint zu klappen.

Auch wenn es mein bisherigen Controller etwas durcheinander wirft.

Muss mir da wohl noch etwas einfallenlassen, das ganze zu strukturieren.

Weil wenn ich das mit dieser Lösung mache, dann brauche ich wieder für jede View ein Query, welches mir das passende Objektgeflecht aus der DB erzeugt.

Ich hatte gehofft, dass das mit Hibernate leichter geht.

Mein Gedanke:
Das einfachste wäre wohl für die komplette Anwendung eine Session geöffnet zu lassen, die dann für das Lazy fetching benutzt werden kann oder birgt das irgendwelche probleme?

Transaktionen kann man ja trozdem noch benutzen.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 02, 2005 4:26 am 
Beginner
Beginner

Joined: Mon Oct 24, 2005 9:46 am
Posts: 22
Location: Germany
Quote:
Das einfachste wäre wohl für die komplette Anwendung eine Session geöffnet zu lassen, die dann für das Lazy fetching benutzt werden kann oder birgt das irgendwelche probleme?


Sessions sind nicht thread-safe!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 02, 2005 4:34 am 
Newbie

Joined: Thu Oct 27, 2005 7:51 am
Posts: 9
Location: Germany
towe wrote:
Sessions sind nicht thread-safe!


Was birgt das denn für ein risiko?
stören sich dann zeitgliche queries?
Auch wenn diese in verschiedenen Transaktionen ablaufen?

Ich implementiere ja keine Webanwendung, wo verschiedene benutzer z.B. in einem Servlet immer auf das gleiche Sessionobjekt zugreifen würden, sonden eine Swing Applikation, wo immer der gleiche Benutzer mit der gleichen Session arbeiten würde.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 02, 2005 6:31 am 
Beginner
Beginner

Joined: Mon Oct 24, 2005 9:46 am
Posts: 22
Location: Germany
Quote:
Was birgt das denn für ein risiko?

du handelst dir ein paar "schöne", kaum zu debuggende RaceConditions ein, wenn du eine einzelne Session über mehrere Threads hinweg nutzt, was auch bei einer Swing-Applikation gegeben sein sollte (es sei denn du lässt wirklich alles, inkl. langen DB-queries & Co. im Event-Dispatch-Thread laufen...)

Dann dürftest du aber auch auf ein weiteres Problem stossen, denn eine Session kann übrigens bis ins unendliche(naja okay, bis zum java.lang.OutOfMemoryError ;-) ) wachsen, da sie alle persistenten Objekte intern cached.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 02, 2005 7:21 am 
Newbie

Joined: Thu Oct 27, 2005 7:51 am
Posts: 9
Location: Germany
OK, überzeugt.
Dann werde ich wol doch den Weg über View => Query eghen müssen.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 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.