-->
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: Help with mapping Primary & Foreign keys with same name
PostPosted: Wed Oct 08, 2008 9:02 am 
Newbie

Joined: Fri Jul 06, 2007 10:01 am
Posts: 10
I have to map two tables shown below using XML mapping.

Header (Table1)
HeaderId *
Name

HeaderDetail (Table2)
HeaderId *
ColumnId *
Desc
Qty

The relationship between Header & HeaderDetail is one to many.
1. Primary Key on Header table is - HeaderId
2. Primary Key on HeaderDetail table are HeaderId & ColumnId

How should I map this? Can anyone share examples of PK & FK with same names?

Thanks in advance!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 08, 2008 3:20 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2008 5:42 am
Posts: 22
Location: Romania
I'm using NHiberante so I will give you an example of how I would do it. I hope it helps.

Header Class mapping:

Code:
<hibernate-mapping default-cascade="none" xmlns="urn:nhibernate-mapping-2.2">
  <class name="Header" table="Header" lazy="true">

    <id name="HeaderId" type="System.Int32" column="HeaderId" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="Name" type="System.String" column="Name" not-null="true" length="50" />

  </class>
</hibernate-mapping>


HeaderDetail Class mapping

Code:
<hibernate-mapping default-cascade="none" xmlns="urn:nhibernate-mapping-2.2">
  <class name="HeaderDetail" table="HeaderDetail" lazy="true">

    <composite-id name="HeaderDetailPrimaryKey" class="PK_HeaderDetail" unsaved-value="any" access="property">
      <key-property name="ColumnId" type="System.Int32" column="ColumnId" />
      <key-many-to-one name="HeaderObj" class="Header">
        <column name="HeaderId" />
      </key-many-to-one>
    </composite-id>
    <property name="Desc" type="System.String" column="Desc" not-null="false" >
    <property name="Qty" type="System.Int32" column="Qty" not-null="false" />

  </class>
</hibernate-mapping>


Because on the HeaderDetail class you have a composed ID in order to work, you need to create also the PK_HeaderDetail class which can look something like this:


Code:
   [System.SerializableAttribute()]
    public class PK_HeaderDetail
    {
        private int columnId;

        private Header headerObj;

        public virtual int ColumnId
        {
            get
            {
                return this.columnId;
            }
            set
            {
                this.columnId= value;
            }
        }

        public virtual Header HeaderObj        {
            get
            {
                return this.headerObj;
            }
            set
            {
                this.headerObj= value;
            }
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (((obj == null)
                        || (obj == System.DBNull.Value)))
            {
                return false;
            }
            PK_HeaderDetail entity = ((PK_HeaderDetail)(obj));
            return ((ColumnId== entity.ColumnId)
                        && (HeaderObj == entity.HeaderObj));
        }
    }


And inside your HeaderDetail class you can have only these properties (virtual):

HeaderDetailPrimaryKey
Desc
Qty


If there is something that you don't understand please post another message and I can clear it out. Good luck !!!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 08, 2008 3:51 pm 
Newbie

Joined: Fri Jul 06, 2007 10:01 am
Posts: 10
tomaandtoma, Thanks for the reply.
Question - Dont you have to map one-to-many relationship in the Header mapping file? I get the Header object which contain a collection of Details.
My Header class looks something like this.

Code:
public class Header {
   
   private long headerId;
   
   private List detailList;

   /**
    *
    */
   public Header() {
      super();
   }
   /**
    * @return Returns the headerId.
    */
   public long getHeaderId() {
      return headerId;
   }
   /**
    * @param headerId The headerId to set.
    */
   public void setHeaderIdId(long headerId) {
      this.headerId = headerId;
   }

   /**
    * @return Returns the details.
    */
   public List getDetailList() {
      return detailList;
   }
   /**
    * @param details The detail to set.
    */
   public void setDetailList(List details) {
      this.detailList = details;
   }
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 09, 2008 2:48 am 
Beginner
Beginner

Joined: Tue Sep 09, 2008 5:42 am
Posts: 22
Location: Romania
I don't know exactly how you can map the bag of HeaderDetail on the Header class but I don't think it's necessary. If you want to retreive all the HeaderDetail for a specific Header you can do like this:

Code:
ISession sess=NHSession.Instance;
ICriteria crit=sess.CreateCriteria(typeof(HeaderDetail));

crit.Add(Expresion.Eq("HeaderDetailPrimaryKey.HeaderObj",myHeaderObject));

IList detailsForMyHeader=crit.List<HeaderDetail>();


What do you think about this approach?

If you want to map the bag on the Header class I'm sure you can find plenty of one-to-many examples on the internet but I suggest this approach.
This way when you load a Header, NHibernate won't have to load all the HeaderDetails for it and you can load the HeaderDetail objects for a specific Header only when needed. I prefer to have my mappings very close to the structure of the tables and not to add any extra info that I can retreive easily with other approaches, but it all depends on the project you are working on. Only you, which knows how all things are binded together, can take the decision over your architecture.

Good luck, my friend!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 09, 2008 9:55 am 
Newbie

Joined: Fri Jul 06, 2007 10:01 am
Posts: 10
Thanks! I tried your suggestion & it works well. As you suggested, I solved it by defining a unidirectional many-to-one relationship. I was initially trying to map bidirectional one-to-many (parent/child) relationship for Header & Details.
Thanks again!!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 09, 2008 10:02 am 
Newbie

Joined: Fri Jul 06, 2007 10:01 am
Posts: 10
Duplicate post!


Last edited by oarl on Thu Oct 09, 2008 11:34 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 09, 2008 10:02 am 
Newbie

Joined: Fri Jul 06, 2007 10:01 am
Posts: 10
Duplicate post.


Last edited by oarl on Thu Oct 09, 2008 11:35 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 09, 2008 10:16 am 
Beginner
Beginner

Joined: Tue Sep 09, 2008 5:42 am
Posts: 22
Location: Romania
You're welcome! I'm glad I could help.


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.