-->
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.  [ 4 posts ] 
Author Message
 Post subject: Many-to-many relationship with composite keys
PostPosted: Tue Aug 30, 2005 2:22 am 
Newbie

Joined: Tue Aug 30, 2005 1:05 am
Posts: 11
Hi,
I have a many to many relationship in between Group and Customer classes. Also Group and Customer classes having one-to-one relationship with Marchant class.

hbm.xml mapping file as follows.

<class name="Marchant" table="Marchants">
<id name="stringId" column="MarchantId" length="50"/>
<property name="marchantName" column="MarchantName" length="200" not-null="true" />
<property name="email" column="Email" length="100" />
<property name="msisdn" column="Msisdn" length="20" />
<property name="lastModifiedDateTime" column="LastModifiedDateTime" type="timestamp"/>
<property name="status" column="Status" length="10" />
<property name="shortCode" column="ShortCode" length="20" />
</class>

<class name="Customer" table="Customers">
<composite-id name="CustomerCompositeId" >
<key-property name="customerId" type="long" column="CustomerId" length="50" />
<key-many-to-one name="marchant" column="MarchantId" />
</composite-id>
<property name="msisdn" column="MSISDN" length="20" unique="true"/>
<property name="shortName" column="ShortName" length="200"/>
<property name="fullName" column="FullName" length="200"/>
<property name="email" column="Email" length="100" unique="true"/>
<set name="groups" table="CustomerGroups">
<key column="CustomerId"/>
<many-to-many column="GroupId" class="Group"/>
</set>
</class>

<class name="Group" table="Groups">
<composite-id name="GroupCompositeId" >
<key-property name="stringId" column="GroupId" length="50" />
<key-many-to-one name="marchant" column="MarchantId" />
</composite-id>
<property name="groupName" column="GroupName" length="100"/>
<property name="description" column="Description"/>
<property name="lastModifiedDateTime" column="LastModifiedDateTime" type="timestamp"/>
<set name="customers" table="CustomerGroups" inverse="true">
<key column="GroupId"/>
<many-to-many column="CustomerId" class="Customer"/>
</set>
</class>

If I'm going to create database table by giving the above hbm.xml mapping file, it throws following exceptions..

org.hibernate.MappingException: Foreign key (FK22573372E1840434:CustomerGroups [CustomerId])) must have same number of columns as the referenced primary key (Customers [CustomerId,MarchantId])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:86)
at org.hibernate.mapping.ForeignKey.setReferencedTable(ForeignKey.java:51)
at org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:976)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:921)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:999)

..............................
...............................
...............................

I think this may be due to some thing wrong with the hbm.xml mapping file.

Can somebody tell me how to solve it?

I really appreciate your help.
Thank you.
thilinaa


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 30, 2005 8:52 am 
Newbie

Joined: Fri Feb 27, 2004 7:55 am
Posts: 17
In your model, a customer is identified by a customerId and a merchantId. Therefore you must also have two keys in the groups definition:

<set name="groups" table="CustomerGroups">
<key column="CustomerId"/>

===> <key column="MerchantId"/>

<many-to-many column="GroupId" class="Group"/>
</set>


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 31, 2005 4:31 am 
Newbie

Joined: Tue Aug 30, 2005 1:05 am
Posts: 11
I have solve the problem by changing the hbm.xml mapping file as follows;
Code:

<class name="Marchant" table="Marchants">
        <id name="stringId" column="MarchantId" length="50"/>
        <property name="marchantName" column="MarchantName" length="200" not-null="true" />
        <property name="email" column="Email" length="100" />
        <property name="msisdn" column="Msisdn" length="20" />
        <property name="lastModifiedDateTime" column="LastModifiedDateTime" type="timestamp"/>
        <property name="status" column="Status" length="10" />
        <property name="shortCode" column="ShortCode" length="20" />
    </class>
    <class name="Customer" table="Customers">
        <composite-id >
            <key-property name="stringId" column="CustomerId" length="50"  />
            <key-many-to-one name="marchant" column="MarchantIdCustomer"  />
        </composite-id>
        <property name="msisdn" column="MSISDN" length="20" unique="true"/>
        <property name="shortName" column="ShortName" length="200"/>
        <property name="fullName" column="FullName" length="200"/>
        <property name="email" column="Email" length="100" unique="true"/>
        <set name="groups" table="CustomerGroups">
            <key>
                <column name="CustomerId"/>
                <column name="MarchantIdCustomer" />
            </key>
            <many-to-many class="Group" >
                <column name="GroupId"/>
                <column name="MarchantIdGroup"/>
            </many-to-many>
        </set>
    </class>

    <class name="Group" table="Groups">
        <composite-id >
            <key-property name="stringId" column="GroupId" length="50"  />
            <key-many-to-one name="marchant" column="MarchantIdGroup"  />
        </composite-id>
        <property name="groupName" column="GroupName" length="100"/>
        <property name="description" column="Description"/>
        <property name="lastModifiedDateTime" column="LastModifiedDateTime" type="timestamp"/>
        <set name="customers" table="CustomerGroups" inverse="true">
            <key>
                <column name="GroupId"/>
                <column name="MarchantIdGroup" />
            </key>
            <many-to-many class="Customer" >
                <column name="CustomerId"/>
                <column name="MarchantIdCustomer"/>
            </many-to-many>
        </set>
    </class>


I can see the created database tables as follows;

Code:

CREATE TABLE Marchants (
  MarchantId varchar(50) NOT NULL default '',
  MarchantName varchar(200) NOT NULL default '',
  Email varchar(100) default NULL,
  Msisdn varchar(20) default NULL,
  LastModifiedDateTime datetime default NULL,
  Status varchar(10) default NULL,
  ShortCode varchar(20) default NULL,
  PRIMARY KEY  (MarchantId)
) TYPE=InnoDB;

CREATE TABLE Groups (
  GroupId varchar(50) NOT NULL default '',
  MarchantIdGroup varchar(50) NOT NULL default '',
  GroupName varchar(100) default NULL,
  Description varchar(255) default NULL,
  LastModifiedDateTime datetime default NULL,
  PRIMARY KEY  (GroupId,MarchantIdGroup),
  KEY FK7FA2C5F4688C34A1 (MarchantIdGroup),
  FOREIGN KEY (`MarchantIdGroup`) REFERENCES `Marchants` (`MarchantId`)
) TYPE=InnoDB;

CREATE TABLE Customers (
  CustomerId varchar(50) NOT NULL default '',
  MarchantIdCustomer varchar(50) NOT NULL default '',
  MSISDN varchar(20) default NULL,
  ShortName varchar(200) default NULL,
  FullName varchar(200) default NULL,
  Email varchar(100) default NULL,
  PRIMARY KEY  (CustomerId,MarchantIdCustomer),
  UNIQUE KEY MSISDN (MSISDN),
  UNIQUE KEY Email (Email),
  KEY FKD7809C35C7E54D5E (MarchantIdCustomer),
  FOREIGN KEY (`MarchantIdCustomer`) REFERENCES `Marchants` (`MarchantId`)
) TYPE=InnoDB;

CREATE TABLE CustomerGroups (
  CustomerId varchar(50) NOT NULL default '',
  MarchantIdCustomer varchar(50) NOT NULL default '',
  GroupId varchar(50) NOT NULL default '',
  MarchantIdGroup varchar(50) NOT NULL default '',
  PRIMARY KEY  (CustomerId,MarchantIdCustomer,GroupId,MarchantIdGroup),
  KEY FK225733727F7EFDF1 (CustomerId,MarchantIdCustomer),
  KEY FK22573372B72C759C (GroupId,MarchantIdGroup),
  FOREIGN KEY (`GroupId`, `MarchantIdGroup`) REFERENCES `Groups` (`GroupId`, `MarchantIdGroup`),
  FOREIGN KEY (`CustomerId`, `MarchantIdCustomer`) REFERENCES `Customers` (`CustomerId`, `MarchantIdCustomer`)
) TYPE=InnoDB;



But the problem is CustomerGroups table have 2 colums (MarchantIdCustomer and MarchantIdGroup) refers to same data, because both MarchantIdCustomer and MarchantIdGroup refers to Merchant class. This results duplicate data.

But I want to have a CustomerGroups table with 3 columns (i.e. CustomerId, MarchantId, GroupId) . MarchantId represents both MarchantIdCustomer and MarchantIdGroup columns in the previous table. (Since both reperesents same thing, I want to make it one)

Is this possible with Hibernate. If so.. how can we change the hbm.xml mapping file?

I really tired with searching this. Sorry for the long comment...

Thank you.
thilinaa


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 31, 2005 11:12 am 
Newbie

Joined: Fri Feb 27, 2004 7:55 am
Posts: 17
In your customer class you can use the marchantId column twice by using a formula element (untested):

Code:
       <set name="groups" table="CustomerGroups">
            <key>
                <column name="CustomerId"/>
                <column name="MarchantId"/>
            </key>
            <many-to-many class="Group" >
                <column name="GroupId"/>
                <formula>MarchantId</formula>
            </many-to-many>
        </set>


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