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.  [ 8 posts ] 
Author Message
 Post subject: one-to-one with foreign key in child table
PostPosted: Fri Nov 21, 2008 10:52 am 
Newbie

Joined: Tue Sep 23, 2008 4:44 pm
Posts: 15
In the example 7.2.2 in hibernate manual, the parent table (PERSON) has foreign key "addressId" of child table. This is reversed, so I want to put the foregin key "personId" in Address table, i.e the Child table should have foreign key of parent.

http://www.hibernate.org/hib_docs/refer ... ional.html

In terms of schema, I want to change the schema from
Code:
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )



to
Code:
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key,  personId foreign key references Person.personId)




I need to
* do that using a foreign key, not join tables.
* be able to navigate from Person->Address.


What needs to change in the mappings(Person.hbm.xml, Address.hbm.xml) and the code(Person.java, Address.java)? Appreciate any responses.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2008 12:12 pm 
Newbie

Joined: Wed Oct 08, 2008 1:54 am
Posts: 14
This should be fairly easy to change.
Regarding the java objects not much would have to be done - depending on some requirements if e.g. a Person can have multiple addresses ...

For such a case I'd suggest something like the following:
Code:
class Person {
    private int id;
    private Set<Address> addresses;
}

class Address{
    private int id;
    private Person person;
}


Furthermore you would have to have mapping files containing the following:
Code:
<class name="Person" table="persons" > 
    [id, other field etc ...]
    <set name="addresses" cascade="all" access="field" >
        <key column="person_id" />
        <one-to-many class="Address" />
    </set>
</class>

<class name="Address" table="addresses" > 
    <id name="id" column="id" type="int" access="field">
        <generator class="increment" />
    </id>

    <many-to-one name="person" column="person_id" not-null="true" foreign-key="FK_ADDRESS_PERSON_ID"/>
</class>


I hope that I understood your problem correctly and that I did not inserted too many typos.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2008 1:20 pm 
Newbie

Joined: Tue Sep 23, 2008 4:44 pm
Posts: 15
Thanks for the response. The requirement is also that Person->Address *must* be a one-to-one mapping. Can you please suggest what needs to be modified for one-to-one case.

Code:
class Person {
  Address address;  // an instance of address

}

class Address {
  // address attributes such as street, city etc.
  // Does *NOT* have person reference

}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2008 2:52 pm 
Newbie

Joined: Wed Oct 08, 2008 1:54 am
Posts: 14
Hmmm if you were using annotations it would be easy because you could just ad a "mappedBy" to the OneToOne annotation of the Person class.
Using mapping-files I searched a bit and found the following issue:
http://opensource.atlassian.com/project ... se/HBX-524
However I was unable to find a reverse one-to-one anywhere in the dtd. Perhaps you would do better using a component ...
THe alternative is to have both entities have each a link to the other one - then you would just add a one-to-one to both mappings.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2008 3:28 pm 
Newbie

Joined: Tue Sep 23, 2008 4:44 pm
Posts: 15
Quote:
THe alternative is to have both entities have each a link to the other one - then you would just add a one-to-one to both mappings.


If I understand correctly, Address class gets changed to have an instance of Parent as below:

Code:
class Address{
  Person person; // an instance of person
  // address attributes

  // getters and setters for person
 
}

If I add this, does this mean that for all instances of Address, I have to call address.setPerson(thePerson) before I can save the person object?

eg:
Code:
Person person = new Person();
Address address = new Address();
person.setAddress(address);
address.setPerson(person);  // need to call this setter?
session.save(person)



can you specify the new mapppings Person.hbm.xml and Address.hbm.xml with the one-to-one mappings?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2008 7:26 pm 
Newbie

Joined: Tue Sep 23, 2008 4:44 pm
Posts: 15
The following mapping (seems to) work for me:

Person.hbm.xml

Code:
<one-to-one name="address"
         class="Address"
         property-ref="person"
         cascade="all"
      />


Address.hbm.xml

Code:
<many-to-one name="person"
      class="Person"
      column="FK_PERSON_ID"
      unique="true"/>



Modified Address.java

Code:
class Address{

  Person person; // added a reference/link to owning entity "Person"
}



Schema
Code:
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key,  FK_PERSON_ID foreign key references Person.personId)


Top
 Profile  
 
 Post subject: one-to-one relationship without a foreign key & lazy loa
PostPosted: Thu Dec 04, 2008 3:22 pm 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
I have the same issue but the child is loading eagerly in separate select statements for no reason:

I have a user and user_termination tables with only the user_termination having the user_id as the foreign key as the user may or may not be terminated (may not have a user_termination entry)!


I defined the userTermination mapping in user as
Code:
<one-to-one name="userTermination" class="UserTermination"
         property-ref="user" lazy="no-proxy">
</one-to-one>


And the userTermination has a user entry as a many-to-one
Code:
<many-to-one name="participant" class="Participant" column="participant_id" unique="true" not-null="false" />


I chose lazy="no-proxy" in my parent however, whenever I write my HQL on parent User table such as

Code:
from User user where user.user_deleted_date_time is null
it fetches all of my user's first in a single select and then follows by a separate select statements of userTermination, obviously whenever they may only exist, although I don't need them to be fetched eagerly unless I do a left join fetch or something!

Any suggestions?

Regards
Rama


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 08, 2008 11:13 pm 
Regular
Regular

Joined: Tue Feb 19, 2008 6:05 pm
Posts: 82
Any help on avoiding the eager loading of the one-to-one child objects that too on a separate select?


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