-->
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: how to set one to many mapping for a composite primary key
PostPosted: Fri Feb 12, 2010 9:39 pm 
Newbie

Joined: Fri Feb 12, 2010 8:11 pm
Posts: 3
Location: NJ
Hi,

I am newbie here. I have 3 tables - User, Address, UserAddresss.


Tables
User table strucutre
userId integer (primary key)
userFirstname char
userLastName char

Address table structure
userAddressId integer (primary key)
Street char
city char
zip char

UserAddress table structure - composite key table
userId integer (primary key) - references User table
userAddressId integer (primary key) - references Address table
Composite Primary Key (userId + userAddressId)

Mapping files
User.hbm.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="UserProfileObj" table="User">
      <id name="uId" type="java.lang.Integer" column="userId">
         <generator class="increment" />
      </id>
      <one-to-many name="userAddress" column="userId" unique="true" not-null="true" insert="false" update="false" />
      <property name="uId">
         <column name="userId" />
      </property>
      <property name="uFirstName">
         <column name="userFirstname" />
      </property>
      <property name="uLastName">
         <column name="userLastName" />
      </property>
   </class>
</hibernate-mapping>

UserAddress.hbm.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="UserAddressObj" table="UserAddress">
      <composite-id>
         <key-property name="uId" column="userId" />
         <key-property name="uAddressId" column="userAddressId" />
      </composite-id>
      <many-to-one name="userId" column="userId" insert="false" update="false" not-null="true" />
   </class>
</hibernate-mapping>

Address.hbm.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="AddressObj" table="Address">
      <id name="uAddressId" type="java.lang.Integer" column="userAddressId">
         <generator class="increment" />
      </id>
      <property name="uStreet">
         <column name="Street" />
      </property>
      <property name="ucity">
         <column name="city" />
      </property>
      <property name="uzip">
         <column name="zip" />
      </property>
   </class>
</hibernate-mapping>


Java objects
Code:
public class UserProfileObj {

    private Integer userId;
    private String uFirstName;
    private String uLastName;

    private List userAddress;
   
    getters/setters....
}

public class UserAddressObj {

    public UserAddressObj() {
    }

    private Integer userId;
    private Integer uAddressId;

    getters/setters....
}

public class AddressObj {

    public AddressObj() {
    }

    private Integer uAddressId;
    private String ustreet;
    private String ucity;
    private String uzip;

    getters/setters....
}


In this case, one User has one or many Addresses.
I am trying to apply Create/Read/Update/Delete (CRUD) operation using hibernate.
I used one-to-many mapping in parent mapping xml and many-to-one in child mapping xml, but no use.
I was getting class should have atleast one meta tag error.

Do I need three mapping files or two is enough? Can anyone fix this mapping files and/or java objects.

I am not sure where is the exact error?

Any help is greatly appreciated.


Thanks,
Sam


Top
 Profile  
 
 Post subject: Re: how to set one to many mapping for a composite primary key
PostPosted: Sat Feb 13, 2010 12:17 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
You are just totally guessing at how to set up a collection. I think you'll really just need to sit down with the documentation and read through the chapters on association mapping:
http://docs.jboss.org/hibernate/core/3.3/reference/en-US/html_single/#collections
http://docs.jboss.org/hibernate/core/3.3/reference/en-US/html_single/#associations

WRT the FKs, you have 2 options.

1) You'll need to "point" the association to a different target. By default, whenever you may a to-one association in Hibernate, it is assumed the target of the underlying FK is the association's PK. That is not the case here. The way to do this is to use the property-ref attribute:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="UserProfileObj" table="User">
      <id name="uId" type="java.lang.Integer" column="userId">
         <generator class="increment" />
      </id>
      <property name="uFirstName">
         <column name="userFirstname" />
      </property>
      <property name="uLastName">
         <column name="userLastName" />
      </property>
      <!-- I am guessing at 'bag' here -->
      <bag name="userAddress" inverse="true" ...>
        <key column="userId" property-ref="" />
        <one-to-many class="UserAddressObj" />
      </bag>
   </class>
</hibernate-mapping>


2) The more natural approach IMO since UserAddressObj is your PK and Address is part of that PK is to do. Below I actually do this for both associations:
Code:
public class UserAddressObj {
    private UserProfileObj user;
    private Address address;

    getters/setters....
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="UserAddressObj" table="UserAddress">
      <composite-id>
         <key-many-to-one name="user" class="UserProfileObj" column="userId" />
         <key-many-to-one name="address" class="AddressObj" column="userAddressId" />
      </composite-id>
   </class>
</hibernate-mapping>



3) Yet another approach is to use a "collection of components" (using UserAddressObj from above...):
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="UserProfileObj" table="User">
      <id name="uId" type="java.lang.Integer" column="userId">
         <generator class="increment" />
      </id>
      <property name="uFirstName">
         <column name="userFirstname" />
      </property>
      <property name="uLastName">
         <column name="userLastName" />
      </property>
      <!-- I am guessing at 'bag' here -->
      <bag name="userAddress" inverse="true" ...>
        <key column="userId" property-ref="" />
        <composite-element class="UserAddressObj">
            <parent name="user"/>
            <many-to-one name="address" class="AddressObj" column="userAddressId" />
        </composite-element>
      </bag>
   </class>
</hibernate-mapping>


4) One last approach, which we generally do not recommend, is to map this as a many-to-many.


Top
 Profile  
 
 Post subject: Re: how to set one to many mapping for a composite primary key
PostPosted: Sat Feb 13, 2010 12:34 pm 
Newbie

Joined: Fri Feb 12, 2010 8:11 pm
Posts: 3
Location: NJ
Steve, Great...that was quick response with detailed options. I appreciate it. I know I was little lazy to read the complete documentation. I read what I needed and tested with composite keys, but no luck.

BTW, which option is the best? I guess option #1. But I was wondering bag is a java.util.List?

Thanks,
Sam


Top
 Profile  
 
 Post subject: Re: how to set one to many mapping for a composite primary key
PostPosted: Sat Feb 13, 2010 12:51 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
If I were developing this, I'd tend to prefer #2 or #3. But that means changing your classes up a bit. It really comes down to how you logically view your "user address". Do you think of it as an entity (in the ERD and O/RM sense)? Or is it merely a dependent object used to bridge between the 2?

<bag/> (as well as <list/> and the others) is described in the documentation in the chapters I linked for you...


Top
 Profile  
 
 Post subject: Re: how to set one to many mapping for a composite primary key
PostPosted: Sat Feb 13, 2010 5:47 pm 
Newbie

Joined: Fri Feb 12, 2010 8:11 pm
Posts: 3
Location: NJ
In my case, User Address in completely a dependent object used to bridge between User and Address. If I go with option #2 or #3, what changes I need to make for java objects.

Thanks for that link...I am going thru it on other side.


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.