-->
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: Surrogate keys and database table relationships
PostPosted: Wed Feb 18, 2009 1:10 am 
Newbie

Joined: Thu May 01, 2008 4:30 pm
Posts: 4
Hello,
I am a newbie at Hibernate so please have patience!
I am using Hibernate 3.1 with Sybase ASE 15.x backend.

I have a question regarding surrogate keys and its effect on table relationships.

Scenario:
Say I have 3 tables.
tb_user: userid char(20) Pri Key, first_name char(40), last_name char40)

tb_user_groups: groupid char(20) Pri Key, group_description char(40)

tb_groupmember: groupid char(20) Pri Key, userid char(20) Pri Key

The above is what we have typically in our databases. I have read that adding a surrogate key column is a good thing as far as Hibernate is concerned, especially for a table like tb_groupmember from above, where otherwise an ID Java class would be neccessary.

So what I did was I added an identity column to each table called "recordid", set it as the Primary Key, and changed the existing Primary key as a unique key instead.

Pretty simple and sensible so far.

Let's say I am working on tb_groupmember. The mapping for this table consists of 2 classes, tbUser and tbUserGroups.

Code:
tbGroupmember.hbm.xml
<hibernate-mapping>
    <class name="com.natixis.web.hibernate.mapping.TbGroupmember" table="tb_groupmember" schema="dbo" catalog="fxrep">
        <id name="recordid" type="java.lang.Integer">
            <column name="recordid" />
            <generator class="assigned" />
        </id>
        <many-to-one name="tbUserGroup" class="com.natixis.web.hibernate.mapping.TbUserGroup" fetch="select">
            <column name="groupid" length="20" not-null="true" />
        </many-to-one>
        <many-to-one name="tbUser" class="com.natixis.web.hibernate.mapping.TbUser" fetch="select">
            <column name="userid" length="20" not-null="true" />
        </many-to-one>
    </class>
</hibernate-mapping>

tbUser.hbm.xml
<hibernate-mapping>
    <class name="com.natixis.web.hibernate.mapping.TbUser" table="tb_user" schema="dbo" catalog="fxrep">
        <id name="recordid" type="java.lang.Integer">
            <column name="recordid" />
            <generator class="assigned" />
        </id>
        <property name="userid" type="java.lang.String">
            <column name="userid" length="20" not-null="true" unique="true" />
        </property>
        <property name="firstName" type="java.lang.String">
            <column name="first_name" length="30" />
        </property>
        <property name="lastName" type="java.lang.String">
            <column name="last_name" length="30" />
        </property>
        <set name="tbGroupmembers" inverse="true">
            <key>
                <column name="userid" length="20" not-null="true" />
            </key>
            <one-to-many class="com.natixis.web.hibernate.mapping.TbGroupmember" />
        </set>
    </class>
</hibernate-mapping>

tbUserGroup.hbm.xml
<hibernate-mapping>
    <class name="com.natixis.web.hibernate.mapping.TbUserGroup" table="tb_user_group" schema="dbo" catalog="fxrep">
        <id name="recordid" type="java.lang.Integer">
            <column name="recordid" />
            <generator class="assigned" />
        </id>
        <property name="groupid" type="java.lang.String">
            <column name="groupid" length="20" not-null="true" unique="true" />
        </propery>
        <property name="description" type="java.lang.String">
            <column name="description" length="100" not-null="true" />
        </property>
        <set name="tbGroupmembers" inverse="true">
            <key>
                <column name="groupid" length="20" not-null="true" />
            </key>
            <one-to-many class="com.natixis.web.hibernate.mapping.TbGroupmember" />
        </set>
    </class>
</hibernate-mapping>


Say I want to perform a search by userid on tb_user_groups. The query would look something like

Code:
from tbUserGroups as model where model.tbUser.userid = ?



What I am seeing is that Hibernate will indeed perform a join between tb_user_groups and tb_user as expected. But instead of doing "tb_user_groups.userid = tb_user.userid", it does "tb_user_groups.userid = tb_user.recordid".

This despite the fact that I have the relationship defined in the tbUserGroups.hbm.xml mapping file as below:
Code:
        <many-to-one name="tbUser" class="com.natixis.web.hibernate.mapping.TbUser" fetch="select">
            <column name="userid" length="20" not-null="true" />
        </many-to-one>


So I am a little confused here. Is there not a way to prevent Hibernate from automatically adding this join to tbUser's primary key which is recordid? It's a surrogate key and holds no business meaning.

I mean, I can see eliminating the surrogate key from tbUser since it doesn't really serve much of a purpose, but I'd like to know if there is a way here.

Perhaps I am doing something terribly wrong here, which wouldn't be out of the question!

Thanks!!!
Nick


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 18, 2009 4:05 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
<many-to-one> joins to the primary key of the referenced table, unless you specify the property-ref attribute. In your case:

Code:
<many-to-one name="tbUser" property-ref="userid" ....>
  ...
</many-to-one>


But, personally I would have kept only the 'recordid' columns from the TbUser and TbGroup in the TbGroupmember mapping. Eg.

Code:
<many-to-one name="tbUser" ....>
  <column name="userrecordid" ... />
</many-to-one>


You also have a similar problem with the <set> mapping in both TbUser and TbUserGroup. The <key>. You'll need a property-ref attribute there are well if you don't want to use the 'recordid' column in the TbGroupmember table.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 18, 2009 12:28 pm 
Newbie

Joined: Thu May 01, 2008 4:30 pm
Posts: 4
I will look into using property-ref. Very much appreciated.

As for keeping the recordid columns from TbUser and TbGroup in TbGroupmember, I see what you mean.

However, being that I am dealing with the so-called "legacy" database schemas, I don't think that will fly with folks around here.

The database isn't necessarily limited to Hibernate based apps so I don't have much leeway in terms of changing the schemas. I had a difficult time having the recordid added as it is!

I will try everything out. Keeping my fingers crossed!

nordborg wrote:
<many-to-one> joins to the primary key of the referenced table, unless you specify the property-ref attribute. In your case:

Code:
<many-to-one name="tbUser" property-ref="userid" ....>
  ...
</many-to-one>


But, personally I would have kept only the 'recordid' columns from the TbUser and TbGroup in the TbGroupmember mapping. Eg.

Code:
<many-to-one name="tbUser" ....>
  <column name="userrecordid" ... />
</many-to-one>


You also have a similar problem with the <set> mapping in both TbUser and TbUserGroup. The <key>. You'll need a property-ref attribute there are well if you don't want to use the 'recordid' column in the TbGroupmember table.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 18, 2009 3:07 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Seems like working with legacy database schemas can be a PITA :). But if you can't point foreign key columns to the primary key of a table (the recordid column) it is questionable how much you have gained by introducing the recordid column in the first place. It still has a use in join tables (eg. TbGroupmember) because, as you say, you don't have to work with composite ID:s. I think it is not so useful with 'recordid' in the other tables that already have a single primary key column if you can't target the 'recordid' from foreign keys.


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.