-->
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.  [ 3 posts ] 
Author Message
 Post subject: parent/child + one of its children as many-to-one in parent
PostPosted: Mon May 17, 2010 12:08 pm 
Beginner
Beginner

Joined: Wed Jul 01, 2009 8:11 am
Posts: 34
Hey,

i'm using an ordinary parent/child relationship of two classes:

Code:
class Child {
   private Parent parent;
}
class Parent {
   private HashSet children;
   private Child specialChild;
}


The not ordinary thing is that the parent not just has a set of the children but also a direct reference to one of its children. Here are the mapping files:

Code:
  <class name="Child">
    <id name="id" type="long">
      <generator class="native"/>
    </id>
    <many-to-one class="Parent" name="parent" not-null="true"/>
  </class>

  <class name="Parent">
    <id name="id" type="long">
      <generator class="native"/>
    </id>
    <many-to-one cascade="all" class="Child" name="specialChild"/>
    <set cascade="all-delete-orphan" inverse="true" name="children">
      <key/>
      <one-to-many class="Child"/>
    </set>
  </class>


The workflow for creating a new Parent looks like this:
Code:
Child specialChild = new Child();
Parent parent = new Parent();
parent.getChildren().add(specialChild);
parent.setSpecialChild(specialChild);
specialChild.setParent(parent);


Therefor both, the parent and the specialChild object, are transient. When using a Hibernate "save" i get the following error:
Code:
Root cause:

org.hibernate.PropertyValueException: not-null property references a null or transient value: components.Parent.specialChild
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:451)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)


The question now is, how to map this? Or how to cope with it?

Thanks in advance and best regards!


Last edited by garz on Thu Jun 03, 2010 12:34 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Mapping problem, transient values
PostPosted: Tue May 18, 2010 9:18 am 
Beginner
Beginner

Joined: Wed Jul 01, 2009 8:11 am
Posts: 34
i found the solution by myself now. it was pretty simple...

set cascade to "delete" only, because if it is set to "all", hibernate tries to cascade-save the specialChild object which result in the described error.

Code:
  <class name="Parent">
    <id name="id" type="long">
      <generator class="native"/>
    </id>
    <many-to-one cascade="delete" class="Child" name="specialChild"/>
    <set cascade="all-delete-orphan" inverse="true" name="children">
      <key/>
      <one-to-many class="Child"/>
    </set>
  </class>


Top
 Profile  
 
 Post subject: Re: Mapping problem, transient values
PostPosted: Thu Jun 03, 2010 12:24 pm 
Beginner
Beginner

Joined: Wed Jul 01, 2009 8:11 am
Posts: 34
the next challenge i'm facing with respect to the described problem is that i cant find a way to persist the specialChild association:

Code:
<class name="Child">
    <id name="id" type="long">
      <generator class="native"/>
    </id>
    <many-to-one class="Parent" name="parent" not-null="true"/>
  </class>

  <class name="Parent">
    <id name="id" type="long">
      <generator class="native"/>
    </id>
    <many-to-one cascade="all" class="Child" name="specialChild"/>
    <set cascade="all-delete-orphan" inverse="true" name="children">
      <key/>
      <one-to-many class="Child"/>
    </set>
  </class>

A run through the debugger showed me that Hibernate nullifies the specialChild association because of the associated child beeing transient.

The question is, is it possible to solve this issue by only altering the mapping?

If not, i already tried to update the Parent object after creation but i'm failing at doing so:
Code:
dao.create(parent);
//after this, parent.specialChild still refers to the correct child object
dao.update(parent);
This is done within one session. Also this:
Code:
parent.setSpecialChild(null);
dao.create(parent);
dao.update(parent);
parent.setSpecialChild(specialChild);
And this:
Code:
parent.setSpecialChild(null);
dao.create(parent);
parent.setSpecialChild(specialChild);
dao.update(parent);

I can't find a solution for this, please help me.


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