-->
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: foreign generator and one-to-one association
PostPosted: Mon Aug 04, 2008 6:14 am 
Newbie

Joined: Mon Aug 04, 2008 5:43 am
Posts: 3
Dear all,

I'm experiencing a problem using the foreign primary key generator with a one-to-one association.
Let me try to describe the situation.

- I have two classes: A and B
- A's id is generated using the hi-lo algorithm.
- B's id is generated using the 'foreign generator'
- there is a one to one association that goes from B to A, constrained set to true

my unit test looks like this:

Code:
A a = new A();

[transaction]
HibernateTemplate.SaveOrUpDate(a);
[transaction closed]

[...]

B b = new B();
b.A = a

[transaction]
HibernateTemplate.SaveOrUpDate(b);
[transaction closed]


I'm expecting b to be saved in the database with b.Id set to a.Id.
Instead, a new instance of A, aa, is created and saved in the database (with aa.Id = a.Id + 1).

At the end of my unit test, i delete b, then a, but aa remains.

I had a look at the source code of NHibernate.Id.ForeignGenerator:

Code:
try
{
    id = ForeignKeys.GetEntityIdentifierIfNotUnsaved(type.GetAssociatedEntityName(), associatedObject, sessionImplementor);
}
catch (TransientObjectException)
{
    id = session.Save(associatedObject);
}


Apparently, a TransientObjectException is raised and Save(a) is called.
My object a is not transient, it should be detached.

I'm using SQL2005, NHibernate 1.2 and Spring 1.1.2
Can you help me with this?

Thank you.

Best regards,

Clement
Code:


Last edited by clement on Mon Aug 04, 2008 9:30 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 7:57 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Can you post the mappings ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 9:22 am 
Newbie

Joined: Mon Aug 04, 2008 5:43 am
Posts: 3
Hi Wolli,

Here are the relevant parts of the mappings.

I was wondering: is the fact of creating A somewhere and B later with a foreign id a valid usecase?
Maybe this foreign generator is meant to always create a pair of two associated object at the same time.

And maybe the way to obtain what i want (asynchronous creation of a and b) is to use assigned ids?

clement


Code:
<!--Class A-->
<class lazy="false" name="namespace.A, Assembly" table="A">
      <cache usage="nonstrict-read-write"/>
      <id name="Id" column="A_Id" type="Int32">
        <generator class="hilo">
            <param name="table">Generator_HILO</param>
            <param name="column">Next_value</param>
            <param name="max_lo">100</param>
        </generator>
     </id>
     <property name="Name" column="A_Name" type="string" not-null="true" />
     <property name="Guid" column="A_Guid" type="Guid" not-null="true" />
     <property name="IsActive" column="A_IsActive" type="boolean" not-null="true" />
     <bag ...>
        ...
     </bag>
     <many-to-one ... />
</class>
   
<!--Class B-->
<class lazy="false" name="namespace.B, Assembly" table="B">
    <cache usage="nonstrict-read-write"/>
    <id name="Id" column="B_Id" type="Int32">
        <generator class="foreign" >            
            <param name="property">A</param>
        </generator>
    </id>
    <one-to-one name="A" class="namespace.A, assembly" constrained="true"/>
  <many-to-one ... />
  <many-to-one ... />
  <many-to-one ... />
  <property ... />      
  <property ... />
  <property ... />
  <property ... />
</class>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 04, 2008 9:42 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Quote:
I was wondering: is the fact of creating A somewhere and B later with a foreign id a valid usecase?
Maybe this foreign generator is meant to always create a pair of two associated object at the same time.


I think you're right here, since the semantic of a one-to-one requires both ends. For doing what you want you need a many-to-one association and then you don't have the problem with the foreign id, since B has it's own id.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 05, 2008 8:39 am 
Newbie

Joined: Mon Aug 04, 2008 5:43 am
Posts: 3
So? What do you think is the final answer?

I read the doc again, it says:

Quote:
Primary key associations don't need an extra table column; if two rows are related by the association then the two table rows share the same primary key value. So if you want two objects to be related by a primary key association, you must make sure that they are assigned the same identifier value!

For a primary key association, add the following mappings to Employee and Person, respectively.

<one-to-one name="Person" class="Person"/>

<one-to-one name="Employee" class="Employee" constrained="true"/>

Now we must ensure that the primary keys of related rows in the PERSON and EMPLOYEE tables are equal. We use a special NHibernate identifier generation strategy called foreign:

<class name="Person" table="PERSON">
<id name="Id" column="PERSON_ID">
<generator class="foreign">
<param name="property">Employee</param>
</generator>
</id>
...
<one-to-one name="Employee"
class="Employee"
constrained="true"/>
</class>

A newly saved instance of Person is then assigned the same primary key value as the Employee instance referred with the Employee property of that Person.



It does not say that the instance of Employee must be "newly saved" as well. On the other hand, it does mention that the one-to-one should be in both class. I don't want A to be aware of B.

So is the doc not clear enough or is it a bug?
Do you know how does it work in hibernate?

I cannot use a many-to-one relation. I can't change the schema, that would break backward compatibility.

I changed the mapping to an assigned Id and made sure the code sets the id of B to A's id before saving.

Clément


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 05, 2008 9:10 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
I can't give you a definite answer, sorry. But changing the mapping to many-to-one wouldn't compromise your schema. You shouldn't have to change it for that.

_________________
--Wolfgang


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.