-->
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.  [ 11 posts ] 
Author Message
 Post subject: unable to load child collection eagerly..
PostPosted: Mon Jun 02, 2008 11:39 pm 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
I have a bi-directional cascade="all" and inverse="true" mapping from a parent to a child with the following mapping files.

Parent.hbm.xml
Code:
        <id name="someId" type="java.lang.Long">
            <column name="SOME_ID" precision="11" scale="0" />
            <generator class="increment" />
        </id>

        <list name="Children" cascade="all-delete-orphan"
              inverse="true" lazy="false">
              <key column="SOME_ID" />
              <list-index column="SOME_SEQNO" base="1"/>
              <one-to-many class="Child" />
        </list>


Child.hbm.xml
Code:
       <id name="ChildId" type="java.lang.Long">
         <column name="CHILD_ID" precision="11" scale="0" unique="true" not-null="true"/>
         <generator class="increment" />
      </id>

        <many-to-one name="parent" column="SOME_ID" class="Parent"
         unique="true" cascade="all" />




I am unable to eagerly load the child list as

Code:
Session session = getSessionInstance();
      try {
         Parent instance = (Parent ) session.get(Parent .class,
               someId);
         return instance;
      } catch (RuntimeException re) {
         re.printStackTrace();
         throw re;
      }

instance.getChildren(); fails to eagerly fetch my children?? any insights into this please??

Code:
root cause

org.hibernate.LazyInitializationException: illegal access to loading collection
   org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:341)
   org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
   org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:109)
   org.hibernate.collection.PersistentList.size(PersistentList.java:91)
   actions.genericAction.CustomReportAction.getSomething(SomeAction.java:216)
   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   java.lang.reflect.Method.invoke(Method.java:597)
   org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:269)
   org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:170)
   org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
   org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
   org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
   org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
   org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:304)
   org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
   org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
   org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
   org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:802)


Thanks
Rama


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 03, 2008 12:16 am 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
For some reason:
fetch="select" WITHOUT lazy="false"
gets the children eagerly??

I always thought lazy="false" is the way to go?

Any comments?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 03, 2008 1:45 am 
Expert
Expert

Joined: Tue Jan 30, 2007 12:45 am
Posts: 283
Location: India
May be your session would have closed.try to call with in open session

_________________
Dharmendra Pandey


Top
 Profile  
 
 Post subject: Can't load children eagerly in bi-directional lazy="fal
PostPosted: Tue Jun 03, 2008 12:04 pm 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
Quote:
May be your session would have closed.try to call with in open session


Dude,

I don't think this is due to the session as I am able to fetch the collection eagerly just by running a query on the parent

public parent SomeDAOMethod()
{
Session session = getSession();
Parent parent = (Parent) "from Parent where someOtherId = ?".setLong(0,SomeOtherIdValue).list
}

In Action class after calling the SomeDAOMethod()
parent.getChilren() works fine

By any chance do you mean I should be calling the children as well inside the DAO to eagerly call the children? Doesn't make much sense :~

Anyways, all I had to do was change from

>>> JUST lazy="false"

to

>>> fetch="select" (WITHOUT lazy="false")

not even, both fetch="select" and lazy="false"

works

But, I have always been using lazy="false" option successfully to get a parent <many-to-one .. > data.

Mostly, I did this parent objects eagerly by saying a left join fetch someObj.parent.parentField....
in my query! I don't think I can do this on the children. Rather a dynamic eager fetching rather than fetching eagerly ALL THE TIME!

However, this time I am trying to get the children eagerly with a <one-to-many .. //see above options I tried// >

What is wrong with this thing??

-Cheers
Rama


Top
 Profile  
 
 Post subject: Re: Can't load children eagerly in bi-directional lazy="
PostPosted: Tue Jun 03, 2008 12:39 pm 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
Just to add to what I posted, my problem is a little contrary to what needs to happen!

From http://www.hibernate.org/315.html

Quote:
Change the global behavior of a particular collection or association in mapping metadata:

* You can switch to an immediate non-lazy second SELECT by setting lazy="false" on a collection or single-valued association mapping.

* You can switch to an immediate non-lazy second SELECT for all single-ended associations to a particular entity class by disabling lazy fetching of the target entity using <class ... lazy="false">. This is only really useful if there are a small number of instances of the entity, and we expect to be able to pull them from the second-level cache.

These settings let you define what part of the persistent graph should be loaded at all times. The how defaults to fetch="select".

* With fetch="join" on a collection or single-valued association mapping, you will actually avoid the second SELECT (hence making the association or collection non-lazy), by using just one "bigger" outer (for nullable many-to-one foreign keys and collections) or inner (for not-null many-to-one foreign keys) join SELECT to get both the owning entity and the referenced entity or collection. If you use fetch="join" for more than one collection role for a particular entity instance (in "parallel"), you create a Cartesian product (also called cross join) and two (lazy or non-lazy) SELECT would probably be faster.


I will be testing again!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 04, 2008 10:15 am 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
I think if you read this article on how hibernate works, you might understand the problem a little more:

http://jpa.ezhibernate.com/Javacode/learn.jsp?tutorial=07howhibernateworks

If you kept your session open longer, you'd have more success. You can use eager loading, but use an open session in view design pattern, and you'll gain great performance and minimize these types of errors.

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 04, 2008 10:18 am 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
Ooops...

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


Top
 Profile  
 
 Post subject: Solved the eager fetching problem, unable to cascade update.
PostPosted: Thu Jun 05, 2008 12:51 am 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
After a couple of days of duel with so many varieties of settings, I realized that my settings have less to do but more with how I am saving my parent and children.

I found that in my bi-directional mapping (parent has a collection list of children and child has a reference of parent) and using Cascade="all-delete-orphan" to be able to add, update and delete children on equivalent changes to parent along with inverse="true" (not sure if how I am using it!).

The problem was that I have been trying to achieve this in two WRONG ways.

1) Creating a parent object first, (obviously not saving it) meaning it does not have the primary key yet. I then created a separate list of children and here was the problem, the parent reference was not included, i.e.,

child.setParent(parentObj) was not included when creating this list of children. I thought that as the parentObj was not persisted yet so it does not make much sense to do that. But I was wrong.
children.add(child);

Anyways, once I created a list of these child objects, I then do a parentObj.setChildren(chidren) and to save both parent and children I can just do session.save(parentObj).

2) I also tried saving parent first, get its object, then followed by saving the children as I have the the parent object stored in each child (bi-directional and child has a reference to parent object) while saving each of the child objects as child.setParent(parentObj).

Problem:
In the first case, it would not save the parent FK in the children. In the second case, where I was saving parent first followed by children, I am using child.setParent(parentObj) only after session.save(parentObj) and so successfully able to insert data into my tables, because I was saving the parent first followed by a individual child entries using a reference of the saved parent object. Note that both were separately done.

However, right after doing this, running a query somewhere later in my application, to access this parent using a brand new query to fetch the parent by its primary key session.find(parent.class,id) and accessing its children using
parentObj.getChildren() gives an empty list although I can see children populated in the child table with the correct parent FK.

Hibernate is somehow getting me the data from its cache I believe, otherwise it should get me all the children AS there are entries in the child table for the given parent FK but it does not as I have already defined how my parent and children are related in my parent.hbm.xml
Is there any thing that can force hibernate to look up or do a fresh load of the parent object and may be it will then include children as well?


Solution: If I save the parent and children by just one session.save(parent) after adding the child collection to parent as parent.setChildren(children) where the children, each had a reference to the parent obj child.setParent(parentObj), I have no problems running a query somwhere later in my application session.find(parent.class,id) and accessing the childCollection eagerly by parentObj.getChildren().


Cameron McKenzie

I will surely look into your inputs and suggestions. Sorry I was more eager to post that I have a working solution to my problem.


-Thanks
Krishna

Parent.hbm.xml

Code:
        <id name="someId" type="java.lang.Long">
            <column name="SOME_ID" precision="11" scale="0" />
            <generator class="increment" />
        </id>

        <list name="Children" cascade="all-delete-orphan"
              inverse="true" lazy="false">
              <key column="SOME_ID" />
              <list-index column="SOME_SEQNO" base="1"/>
              <one-to-many class="Child" />
        </list>


Child.hbm.xml
Code:
       <id name="ChildId" type="java.lang.Long">
         <column name="CHILD_ID" precision="11" scale="0" unique="true" not-null="true"/>
         <generator class="increment" />
      </id>

        <many-to-one name="parent" column="SOME_ID" class="Parent"
         unique="true" cascade="all" />


I am unable to eagerly load the child list as

Code:
Session session = getSessionInstance();
      try {
         Parent instance = (Parent ) session.get(Parent .class,
               someId);
         return instance;
      } catch (RuntimeException re) {
         re.printStackTrace();
         throw re;
      }


Top
 Profile  
 
 Post subject: Unable to save parent and children as cascade
PostPosted: Thu Jun 05, 2008 1:14 am 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
I am trying to save the parent with a new child list by just saying

1) load the parentObj

I can see that it also eagerly fetches the existing children

2) create a new list of children with a reference of the parent object
as in child.setParent(parentObj) as mine is a bi-directional relationship

3) save this list to parent and save the parent.
parentObj.setChildren(newChildrenList);
session.save(parentObj)

I end up getting an error:
org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: database.Parent.children

Any idea why I am getting this error? and how am I suppose to let Hibernate intelligent enough to delete existing children list (delete existing child entries) and add a new children (insert new child entries)?


Thanks
Krishna


Top
 Profile  
 
 Post subject: help needed in deleting a collection!
PostPosted: Fri Jun 06, 2008 2:01 am 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
still waiting for an answer 'to my above post' as to why I cannot delete a collection in a bi-directional cascade="all-delete-orphan" inverse="true" mapping?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 19, 2008 10:44 pm 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
Looks like if I do a

Code:
parent.setChildren(newChildList)


I get a child collection dereferenced exception.

Is the only way to iterate each child, remove each one by one and then saveorUpdate this parent???. The problem is that I have many children about 50-100 as a collection.

Then again I add new children again one by one, and then using another saveOrUpdate again to add new children to a parent.

Thanks
Krishna


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