-->
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.  [ 7 posts ] 
Author Message
 Post subject: Saving from child on Parent/Child relationship
PostPosted: Fri Aug 27, 2004 12:14 pm 
Newbie

Joined: Thu Aug 26, 2004 9:25 am
Posts: 8
Hi all,
I have a parent class P, a child class C (as many-to-one relation), It generate a foreign key on child table.
Class c, has a memever variable wich holds a reference to parent.
Does anybody knows if it is possible save both, child and parent from a child instance if both are transient ???
I've been making some tries of session.save(child), but I've got FK Contraints from the db because, because It doesn't save the parent at first place in order to get de fk for the child.
Thanks in advance.



Hibernate version:

Mapping documents:

Code between sessionFactory.openSession() and session.close():

Full stack trace of any exception that occurs:

Name and version of the database you are using:

Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 27, 2004 3:40 pm 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
Please check out Chapter 16: Example Parent/Child from Hibernate docs.


Top
 Profile  
 
 Post subject: Similar problem -- immutable child, both not persisted (yet)
PostPosted: Tue Oct 05, 2004 6:28 am 
Newbie

Joined: Wed Oct 15, 2003 1:52 am
Posts: 7
Hi,

I'm having a similar problem, and chapter 16 of the Hibernate docs doesn't seem to relate all that well. We're using Hibernate in a large project, and are in the process of cleaning up/optimizing the mapping file. We are running Hibernate 2.1.6, on Oracle.

We have:

- parent doesn't reference children
- child class references one parent (many-to-one)
- child class has mutable='false'
- child -> parent relationship has cascade='save-update'
- child -> parent relationship has not-null='true'
- both child and parent are unsaved

We are working in a transaction.

What seems to happen is that Hibernate writes the child class first, but the link to parent is null (because parent doesn't have an id yet). It then (I assume) writes the parent, generates its id, then updates the child.

This, of course, causes problems with the not-null on the child mapping. If we take out the not-null, then the database becomes inconsistent -- Hibernate doesn't update the child with the parents ID, presumably because the child is supposed to be immutable. So that's even more of a problem.

Basically, we want the relationship to be not-null, and for the child objects to be immutable -- that's the way it should be, for our design.

Is there any way we can get around this, just using Hibernate (not recoding our own cascade solution)?

Regards

Simon Russell


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 6:32 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
This is an FAQ and your model is not consistent and could be considered broken:

A not null constraint on the FK column in table B (the child table) means that every instance of class B has to have a reference to an instance of class A at all times. Otherwise, it wouldn't be valid. These are the semantics of your relational model, thats why you used a constraint in the first place.

All of this has to be reflected in your object model. If you don't want to have the reference from B to A (only from A to B, which is unrelated to this problem), don't enforce it with a constraint.

Hibernate is doing nothing wrong and there is no way for Hibernate to solve this situation. Its the correct behavior for your data model.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 7:11 pm 
Newbie

Joined: Wed Oct 15, 2003 1:52 am
Posts: 7
I'll assume I didn't explain myself properly, since your answer doesn't seem to relate -- if this is a FAQ question (I couldn't find it), would you be able to provide a link?

The not-null constraint is accurate -- every instance of the child table (B in your reply) _does_ have to have a reference to the parent (A in your reply) _all the time_. Straight after construction, this is true (the parent is a parameter to the constructor). The child _never_ has a null parent, whatsmore, there are asserts in the getParent/setParent that make sure it is never null.

We _only_ have the reference from child to parent (B to A). We don't have a reference from parent to child (A to B). Both constraints are accurate, and fit our model exactly. It just was previously only enforced by contract in our code, not in the hibernate mapping.

The problem seems to be that Hibernate is writing an incomplete immutable child instance, then the parent, then attempting to update the child. But on the first write of the child instance, the parent column will appear to be null, because the parent doesn't have an id yet (it hasn't been saved).

What really needs to happen is for Hibernate to save the parent _before_ it saves the child, so that the parent gets an id. This probably needs to be an option on the cascade property.

Regards

Simon.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 12, 2004 12:26 am 
Newbie

Joined: Mon Oct 11, 2004 11:19 pm
Posts: 2
G'day,

I can see what etoastw and mpisano are saying. I have the same problem but I will pose it in the form of a relational object instead of a parent child relationship. I have simplified my problem to its barest. (I also use 2.1.6 on Oracle)

Take the following classes, where ClassB stores classA and ClassC (and maybe some extra data):

<!-- ClassA -->
<class name='hibernatetest.ClassA' table='CLASSA'>
<many-to-one name='classB' class='hibernatetest.ClassB' cascade='save-update' not-null='true'/>
</class>

<!-- ClassB -->
<class name='hibernatetest.ClassB' table='CLASSB' mutable='false'>
<many-to-one name='classA' class='hibernatetest.ClassA' />
<many-to-one name='classC' class='hibernatetest.ClassC' cascade='save-update' not-null='true'/>
</class>

<!-- ClassC -->
<class name='hibernatetest.ClassC' table='CLASSC'>
<property name='someData' not-null='true' />
</class>

ClassA's constructor creates a ClassC and the relationship ClassB.

So the only code needed in the transaction is:

classA newA = new ClassA();
session.save(newA);

What I think happens is that the "cascade='save-update'" on ClassA goes to save classB first, ClassB then tries to save classA, this is where it gets interesting, if you make the classA property "not-null='true'" it will throw a PropertyValueException because it is trying to save classA while it is still transient (though we explicitly called save on a ClassA).
BUT
If you don't have not-null set it will behave like it worked but the DB column for ClassA will be left null! Which will only show itself when you try and load the object or manually check it. This is bad and is caused by the need to have ClassB immutable.

Is there a way to tell ClassB to save AFTER classA? One solution (maybe) is to make an interceptor that somehow manages the save order, but that doesn't seem nice.

Of course the real code is much more complicated but the basic problem still exists.

Cheers

Paulie


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 12, 2004 12:36 am 
Newbie

Joined: Mon Oct 11, 2004 11:19 pm
Posts: 2
OK now that it is out there, some may say it is a circular dependency or some such, but there is nothing wrong with this example as a basic object model.

I was also under the impression that it is not really commited until commit is called, this says to me that it should be possible (in theory) to assign them both objectid's before commiting to the DB.

Paulie


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