-->
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.  [ 9 posts ] 
Author Message
 Post subject: one-to-one and setting FK id
PostPosted: Wed Jan 07, 2004 8:45 pm 
Newbie

Joined: Wed Jan 07, 2004 8:22 pm
Posts: 5
DB:
Code:
create table person
(
   personid number not null,
   thename varchar2(100) null,
   constraint pk_person primary key (personid)
);
create sequence personseq increment by 1 start with 1;

create table address
(
    addressid number not null,
    personid number not null,
    theaddress varchar2(100) null,
    constraint pk_address primary key (addressid),
    constraint fk_person foreign key (personid) references person(personid)
  );
  create sequence addressseq increment by 1 start with 1;


Objects:
Person object has
id, name, Address (the whole Address object)

Address object has
id, address, personId (not a Person object, just the id)


Mapping:
Code:
<hibernate-mapping>
    <class  name="Person"  table="PERSON">
        <id name="id" column="PERSONID">
            <generator class="sequence">
                <param name="sequence">PERSONSEQ</param>
            </generator>
        </id>
        <property name="name" column="THENAME"/>
       <one-to-one name="address" class="Address"  cascade="save-update" constrained="true" property-ref="personId"/>
    </class>

    <class name="Address" table="ADDRESS">
        <id name="id" column="ADDRESSID">
            <generator class="sequence">
                <param name="sequence">ADDRESSSEQ</param>
            </generator>
        </id>
        <property  name="address" column="THEADDRESS"/>
        <many-to-one  name="personId" class="Person"
            cascade="save-update" column="PERSONID"           unique="true"/>
    </class>

</hibernate-mapping>


So, I want to be able to load my person, and automatically get my Address. The Person doesn't have an Address link it's table, so I want to use the one-to-one and have it load a record from the Address table. But, I get ahead of myself, my question is on the save.

I create a new Person object, and a new Address object.
Code:
    Person person = new Person();
    Address address = new Address();
    address.setAddress("myaddress");
    person.setAddress(address);
    person.setName("myname");


When I save the Person object, the person gets an id populated (great!), the Address in the Person gets an id (great!), but the personId in the Address, which should be populated with the newly created PersonId, remains null, which fails the insert.

Shouldn't the nested PesonId be populated on a save? Seems sort of useless to have a one-to-one mapping that doesn't actually set the foreign key id when saving. I assume I have something set incorrectly here. Could somebody elighten me?

BTW, I cannot switch it to have an addressId in the person table (obviously simplified examples of my real situation). I need to work with the Person object exclusively. That is, I need to be able to create/save/update Person objects and have the changes to Address objects flow from there.

Thanks in advance,

-- Dave


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 07, 2004 8:50 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Address object has
id, address, personId (not a Person object, just the id)

Well, this is obviously not a many-to-one in the Adress class. Map it as a property.


Top
 Profile  
 
 Post subject: I had it as a property
PostPosted: Wed Jan 07, 2004 8:54 pm 
Newbie

Joined: Wed Jan 07, 2004 8:22 pm
Posts: 5
I had it as a property first, then followed the examples on bidirectional one-to-one relationships hoping that it would make a difference. I saw no difference. In either case, the personId in the Address is not populated.

-- Dave


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 07, 2004 8:54 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Quote:
BTW, I cannot switch it to have an addressId in the person table (obviously simplified examples of my real situation). I need to work with the Person object exclusively. That is, I need to be able to create/save/update Person objects and have the changes to Address objects flow from there.


Still do not understand why you can't move addressId into Persons table. You will be able to update Person object as you wish and address will remain the same. Only when you actually modify any of the Address properties, UPDATE statement will be issued to Address table.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 07, 2004 8:56 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
To late here for me to think properly, but: Set the personId property of Address manually in your setAdress() method in Person class.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 07, 2004 9:13 pm 
Newbie

Joined: Wed Jan 07, 2004 8:22 pm
Posts: 5
dimas wrote:
Still do not understand why you can't move addressId into Persons table. You will be able to update Person object as you wish and address will remain the same. Only when you actually modify any of the Address properties, UPDATE statement will be issued to Address table.


The way the db is set up, which I can't change, is that there are "parent" tables and "child" tables. The "child" tables have references to the parents, and not vice versa. In this case, the parent and child tables are one parent to one child, not one parent to many children. The Person/Address is just an illustration of that. So, I need to be able to load my parent and get my children objects. I've done this sucessfully with sets in the one parent to many children case, but I'd like to avoid that here. I'd rather not create a HashSet which I know will only have 1 entry.

-- Dave


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 07, 2004 9:17 pm 
Newbie

Joined: Wed Jan 07, 2004 8:22 pm
Posts: 5
gloeglm wrote:
To late here for me to think properly, but: Set the personId property of Address manually in your setAdress() method in Person class.


I can't set it manually, it's in the middle of a save.
session.save(person)

I could do it before the flush, but I don't really want to save, then go through my other objects settings ids. Seems like an unnessary step, something that should be done automatically with the one-to-one mapping, just like it works if I had a <set>.

Again, I could convert this to a set, but this seems to me exactly what the one-to-one is supposed to be for, a <set> of 1.

-- Dave


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 08, 2004 3:22 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
The problem is simple:

remove constrained="true" from the <one-to-one> element, since the FK faces in the other direction.

There is an example of this in sect 5.1.11


Top
 Profile  
 
 Post subject: bi-directional required?
PostPosted: Thu Jan 08, 2004 8:41 am 
Newbie

Joined: Wed Jan 07, 2004 8:22 pm
Posts: 5
gavin wrote:
The problem is simple:

remove constrained="true" from the <one-to-one> element, since the FK faces in the other direction.

There is an example of this in sect 5.1.11


Okay, I got this working, but I'm still confused. The 5.1.11 section says
Quote:
property-ref: (optional) The name of a property of the associated class that is joined to the primary key of this class. If not specified, the primary key of the associated class is used.


That implies, to me, that I can have a Person class, which has an Address object, defined with this mapping:
Code:
   <id name="id" column="PERSONID">
            <generator class="sequence">
                <param name="sequence">PERSONSEQ</param>
            </generator>
        </id>
        <property name="name" column="THENAME"/>
       <one-to-one name="address" class="Address"  cascade="save-update" property-ref="personId"/>
    </class>
    <class name="Address" table="ADDRESS">
        <id name="id" column="ADDRESSID">
            <generator class="sequence">
                <param name="sequence">ADDRESSSEQ</param>
            </generator>
        </id>
        <property  name="address" column="THEADDRESS"/>           
        <property  name="personId" column="PERSONID"/>
    </class>



Note that the property-ref is referencing an ID on the Address, not a person object. This is my understanding of what is described in 5.1.11. The property-ref is associated to the property that holds the primary key of the Person object. The mapping above doesn't work. It does not populate the property-ref property with the new id when saving.

I did get it to work with the mapping below. I removed the personId field from Address and put a Person object in there instead, making it a true bi-directional relationship. I then change the property-ref to refer to the Person object property in Address, not the property that holds a primary key to the Person, as indicated in section 5.1.11.

Code:
   <id name="id" column="PERSONID">
            <generator class="sequence">
                <param name="sequence">PERSONSEQ</param>
            </generator>
        </id>
        <property name="name" column="THENAME"/>
       <one-to-one name="address" class="Address"  cascade="save-update" property-ref="person"/>
    </class>
    <class name="Address" table="ADDRESS">
        <id name="id" column="ADDRESSID">
            <generator class="sequence">
                <param name="sequence">ADDRESSSEQ</param>
            </generator>
        </id>
        <property  name="address" column="THEADDRESS"/>   
        <many-to-one name="person" class="Person"
            cascade="save-update" column="PERSONID"/>
    </class>



In short, the one-to-one appears to only work if the mapping is bidirectional. My impression from 5.1.11 is that the bidirectionality was optional, not required.

Can somebody clarify this for me? Especially the intended use of the property-ref, which talks of a property containing a foreign-key, not a foreign object.

Thanks[/quote]


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