-->
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.  [ 6 posts ] 
Author Message
 Post subject: Problems with refresh after an insert
PostPosted: Mon Mar 02, 2009 5:00 pm 
Newbie

Joined: Fri Feb 13, 2009 5:43 pm
Posts: 4
Hibernate version: 3.2.3GA
Oracle: 10.2:

I have a parent-child-grandchild relp similar to the following:

Code:
public class Parent {
   Set<Child> children ;
   ...
   
   @OneToMany(mappedBy="parent")
   @JoinColumn(name="PARENT_ID")
   @Cascade( {CascadeType.SAVE_UPDATE, CascadeType.REFRESH})
   public Set<Child> getChildren() {
      return children ;
   }
   public void setChildren( Set<Child> _set ){
      children = _set ;
   }
}
public class Child {
   Parent      parent ;
   Set<GrandChild> grandChildren ;
   
   Language language ;
   
   @OneToMany(mappedBy="child")
   @JoinColumn(name="CHILD_ID")
   @Cascade( {CascadeType.SAVE_UPDATE, CascadeType.REFRESH})
   public Set<Child> getGrandChildren() {
      return grandChildren ;
   }
   public void setGrandChildren( Set<GrandChild> _set ){
      grandChildren = _set ;
   }
   
   @ManyToOne
   @JoinColumn(name="LANGUAGE_ID")
   public Language getLanguage() {
      return language ;
   }
   public void setLanguage( Language lang ) {
      language = lang ;
   }
   
   
   @ManyToOne
   @JoinColumn(name="PARENT_ID")
   public Parent getParent() {
      return parent ;
   }
   public void setParent( Parent _parent) {
      parent = _parent ;
   }
   
}

public class GrandChild {
   Language language ;
   Child   child ;

   @ManyToOne
   @JoinColumn(name="LANGUAGE_ID")
   public Language getLanguage () {
      return language ;
   }
   public void setLLanguage ( Language lang ) {
      language = lang ;
   }
   
   @ManyToOne
   @JoinColumn(name="CHILD_ID")
   public Parent getChild() {
      return child;
   }
   public void setChild( Child _parent) {
      child = _parent ;
   }
}

AND
public class Language {
   Child   child ;
   GrandChild   grandChild;
   String   description ;
   
   @ManyToOne
   @JoinColumn(name="LANGUAGE_ID")
   public Parent getChild() {
      return child;
   }
   public void setChild( Child _parent) {
      child = _parent ;
   }
   
   @ManyToOne
   @JoinColumn(name="LANGUAGE_ID")
   public Parent getGrandChild() {
      return grandChild;
   }
   public void setGrandChild( GrandChild _parent) {
      grandChild = _parent ;
   }
   

}



When I insert a new Child to the parent, I have no problems with a refresh on the Parent. But when I
insert a grandchild, and perform refresh on the Parent, it seems that the grandchild is not refreshed.
Here is the code snipped of update / refresh ( within one @Transactional method ) .

Code:
   
        session.flush( parent ) ;
   session.persist( parent );      /// Inserts gc to the DB.
   session.refresh( parent );
   
   ...
   // Following generates null pointer exception
   for ( GrandChild gc : child.getGrandChildren() ) {
      System.out.println( gc.getLanguage().getDescription ) ;    
      // -- the getLanguage on the gc recently added is null 
   }


When I turn sql debugger on - I can see that the SQL call to Language table is not being called for
the inserted object ( it is being called at initial retrieval time ) .

I'm at a loss here why the grandchildren is behaving differently - Am hoping someone can shed some light.

Thanks in advance ..


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 02, 2009 5:57 pm 
Beginner
Beginner

Joined: Sun Dec 28, 2008 6:01 pm
Posts: 24
Could we take a look at the mapping files (.hbm.xml) for these classes?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 02, 2009 6:22 pm 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
Does it work when you call refresh(child)?

I haven't tried it out yet but maybe the mappedBy conflicts with the cascading refresh as it ignores inserts? just a really long shot...

sidenote: why is language to child/grandchild many-to-one, shouldn't that be one-to-many?

Are your objects inserted and read in the same transaction?
If you chain of @Transactional methods is broken this might have side effects, then you have to refresh every object along the way.

So if in your example child.getGrandChildren does work (= return collection instead of null) then refresh(gc), then retrieve the language only and refresh the language object too, then retrieve description. Does that work?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 03, 2009 12:18 pm 
Newbie

Joined: Fri Feb 13, 2009 5:43 pm
Posts: 4
Thx for all your replies.

The refresh on the child works. However I like to avoid that , as I would have to iterate thru the collection of children and refresh each one.
Plus later implementation involves great-grand-children and great-great-grand-children.

Sidenote to language: Each child / grandchild is associated to one language - hence many-to-one.

Yes I am inserting and refreshing under same transaction. The more I think about it, that maybe my problem. At initial glance - I was having difficulty seperating it out - but I will spend today looking at the option closer.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 03, 2009 5:36 pm 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
Are you using Spring for you transactions?

you probably misread my comment on language, i understand that the direction child/grandchild > language is many-to-one but not the other way round that language > child/grandchild is many-to-one too (it should be one-to-many)

child - many-to-one - language
language - one-to-many - child

rating is welcome


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 05, 2009 11:44 am 
Newbie

Joined: Fri Feb 13, 2009 5:43 pm
Posts: 4
Sorry - I forgot to mention that I was using Spring 2.5.
And sorry again - language should be a one-to-many relp.

After a bit of digging i found a solution - which I've outlined below. Apologies in advance for my verboseness .
- I had annotated a private method as @Transactional. Not the right thing to do according to http://static.springframework.org/spring/docs/2.5.x/reference/transaction.html#transaction-declarative-annotations .
- Decided that refresh() was not appropriate for my situation as manually refreshing each of the grandchildren was not an option
- Instead, after my save ( via persist ) , I wound up clearing the session and reloading the parent object via a findById().

I'm not convinced the last point is the most efficient solution - as it will hit the DB more than really necessary ( for our scenario ) . The alternative is then at insert time, when creating the new GrandChild Object, retrieve the Language object and associate to Grandchild ( so that the GrandChild object is complete ) . Yes , reloading the entire Parent object is a cleaner solution but if timing is an issue ... I'm bringing these issues to the rest of our dev team - and we will proceed from there.

Also I apologize if this wasn't the right forum to post original question - as I am using a combo of Hibernate / Spring.

Thx ..


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