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.  [ 5 posts ] 
Author Message
 Post subject: Cascades around circular associations
PostPosted: Wed Apr 02, 2008 3:00 pm 
Newbie

Joined: Wed Apr 02, 2008 2:31 pm
Posts: 2
Hi,

Is there anyone out there who could help shed some light on a bug/feature that has been troubling me recently. It appears when there are two classes, A and B, which are connected via a bi-directional one-to-many association and a unidirectional many-to-one from A to B, all with cascade on save-update.

I have put together a simple test case:

Classes:

public class Child {

private java.lang.String _name;
private Parent _parent;
protected java.lang.Long _id;

// standard getters and setters ...

}

public class Parent {

private java.lang.String _name;
private java.util.Set<Child> _children;
private Child _specialChild;
protected java.lang.Long _id;

// standard getters and setters
}

Mappings:

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

<hibernate-mapping auto-import="false">
<class
name="Parent"
table="PARENT"
>

<id
name="dbId"
column="DBID"
type="java.lang.Long"
>
<meta attribute="scope-set">protected</meta>
<generator class="native"/>
</id>

<property
name="name"
type="java.lang.String" length="80"
>
<column name="NAME" sql-type="VARCHAR(80)" length="80" />
</property>

<many-to-one
name="SpecialChild"
column="SPECIALCHILDID"
class="Child"
cascade="merge,save-update"
not-null="false"
unique="false"
>
</many-to-one>

<set
name="Children"
table="CHILD"
inverse="true"
cascade="all"
>
<key column="CHILDID"/>
<one-to-many class="Child"/>
</set>

</class>

<class
name="Child"
table="CHILD"
>

<id
name="dbId"
column="DBID"
type="java.lang.Long"
>
<meta attribute="scope-set">protected</meta>
<generator class="native"/>
</id>

<property
name="name"
type="java.lang.String" length="80"
>
<column name="NAME" sql-type="VARCHAR(80)" length="80" />
</property>

<many-to-one
name="Parent"
column="PARENTID"
class="Parent"
cascade="merge,save-update"
not-null="true"
unique="false"
>
</many-to-one>

</class>

</hibernate-mapping>

Test code:

import org.hibernate.Session;
import org.hibernate.FlushMode;
import util.HibernateUtil;

public class Test {

static public void main(String[] args) {

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();

Parent p = new Parent();
p.setName("dad");

Child c1 = new Child();
c1.setName("Bob");
c1.setParent(p);

java.util.Set<Child> cs = new java.util.HashSet<Child>();
cs.add(c1);

p.setChildren(cs);
p.setSpecialChild(c1);

session.save(p);

session.getTransaction().commit();
}
}

Error (I can send the whole stack trace if necessary, but it is huge).

[java] Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value: Child.Parent
[java] at org.hibernate.engine.Nullability.checkNullability(Nullability.java:84)

It appears to be a problem with the status of the Parent property at the time that the Child is being saved (it is flagged as SAVING rather than MANAGED) but I simply don't know enough about the guts of hibernate to see what could be causing this. Any help would be much appreciated.

If I remove the cascade on the unidirectional association (specialChild) then it works. If I don't call setSpecialChild in the test script it works too. So presumably it comes down to the way in which circular associations are handled.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 02, 2008 4:43 pm 
Newbie

Joined: Tue Mar 04, 2008 12:12 am
Posts: 7
Location: Wellington, New Zealand
you should be marking either of the parents child property, or the childs parent property as inverse="true"

I'd recommend the child property on the parent - the generated SQL will be simpler.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 03, 2008 4:08 am 
Newbie

Joined: Wed Apr 02, 2008 2:31 pm
Posts: 2
Astaro wrote:
you should be marking either of the parents child property, or the childs parent property as inverse="true"

I'd recommend the child property on the parent - the generated SQL will be simpler.


That is how it is currently set up (the Children property on Parent has inverse="true"). The other association is unidirectional so does not have any inverse flag.

Of course, in theory with this arrangements of classes I could set up the unidirectional association as a flag in the child, although there are good reasons why I have to maintain this informaiton in the Parent in this particular case.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 07, 2008 11:19 am 
Newbie

Joined: Wed Apr 26, 2006 4:31 am
Posts: 2
add
session.save(c1);
before
session.save(p);
will solve the problem


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 07, 2008 11:47 am 
Newbie

Joined: Wed Apr 26, 2006 4:31 am
Posts: 2
you have an error in your mapping of Child:
column="PARENTID"
should be
column="CHILDID"


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