-->
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.  [ 12 posts ] 
Author Message
 Post subject: Mapping a denormalized table
PostPosted: Tue Feb 07, 2006 11:21 am 
Newbie

Joined: Mon Jan 30, 2006 10:53 pm
Posts: 7
I'm trying get NHibernate to work with tables that are not normalized properly (and I can't do anything about it). I posted this as part of another question last week, but nobody addressed this part.

Here is a sample table:

CONTACT1
COMPANY, ... PHONE1, PHONE2, PHONE3

I'm having trouble dealing with the multiple PHONE fields. I want them each in there own class of:

PhoneNumber
Number


Here is a sniplet of my current mapping file. It currently only supports accessing the PHONE1 field and ignores the rest:

Code:
  <class name="Contact" table="CONTACT1" mutable="false">
    <id name="Id" column="AccountNo" type="String">
      <generator class="assigned" />
    </id>

    <bag name="PhoneNumbers" inverse="true">
      <key column="AccountNo" />
      <one-to-many class="PhoneNumber" />
    </bag>
  </class>

  <class name="PhoneNumber" table="CONTACT1" mutable="false">
    <id name="Id" column="AccountNo" type="String">
      <generator class="assigned" />
    </id>
    <property name="Number" column="PHONE1" />
  </class>




If it makes a difference, this class only needs to reads the data, it does not write it back.

I'm very new to Hibernate and I'm trying to wrap my head around all of this. I've read the documentation on hibernate.org but I couldn't find any example like this... if anyone can point me in the right direction I'd be very appreciative.

Thanks,
Patrick


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 8:13 pm 
Senior
Senior

Joined: Wed Jun 15, 2005 4:17 am
Posts: 156
I think you have two options:

1. create some views in the database to normalise your data. I have used this approach in the past and works nicely if you need only read access to your data.

2. other approach would be to declare your phone1,phone2, phone3 as private members of your object and define in your object as a public property the collection of PhoneNumbers. you can initialize the collection in the constructor or lazily in your getter. In this way you can keep the mess private.

HTH,
radu


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 11:17 pm 
Newbie

Joined: Mon Jan 30, 2006 10:53 pm
Posts: 7
Thanks for the reply, unfortunately neither solution would work in my case. I realize creating a view could help solve the problem, but I'm trying to avoid that.

I also can't have the phone numbers just stored as strings in a collection, they need to be each in their own class (and then a collection a PhoneNumber objects contained in the Contact object)

I'm starting to get the feeling that Hibernate does not support what I'm trying to do.

Thanks,
Patrick


Top
 Profile  
 
 Post subject: Try mapping it as a Collection of Components
PostPosted: Wed Feb 08, 2006 12:40 am 
Regular
Regular

Joined: Tue Jan 03, 2006 7:21 am
Posts: 85
Try mapping your scenario as a Collection of Components. Please see following url's for documentation:

http://www.hibernate.org/hib_docs/reference/en/html/components.html

http://ndpsoftware.com/HibernateMappingCheatSheet.html


Top
 Profile  
 
 Post subject: Try mapping it as a Collection of Components
PostPosted: Wed Feb 08, 2006 12:42 am 
Regular
Regular

Joined: Tue Jan 03, 2006 7:21 am
Posts: 85
Try mapping your scenario as a Collection of Components. Please see following url's for documentation:

http://www.hibernate.org/hib_docs/reference/en/html/components.html

http://ndpsoftware.com/HibernateMappingCheatSheet.html


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 1:35 am 
Newbie

Joined: Mon Jan 30, 2006 10:53 pm
Posts: 7
Samujab,

But how do components help me instantiating 3 separate phone number classes? I've read the docs, I just re-read that section now, I don't see how this can help. Can you show me?

I need to map 3 PhoneNumber objects (as a separate classs, not an array of strings or other structures) to one Record.

Thanks, sorry if I'm dense,
Patrick


Top
 Profile  
 
 Post subject: Sorry
PostPosted: Wed Feb 08, 2006 4:14 am 
Regular
Regular

Joined: Tue Jan 03, 2006 7:21 am
Posts: 85
I did not fully understand your problem before suggesting to try a collection of Components.

Have you tried if creating a Custom User type could help solve this problem. Let me see if I can come up with an example.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 5:07 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
dpseal, you need to understand that bag (and other collections as well) can't help you in this case. Collections are for mapping data that resides in another table, binded by means of foreign key.
As radu suggested you need to:
1. Map your fields with phone numbers into three separate members of your "Contact" class. Those members could be private and they could be either strings, or instances of your "PhoneNumber" class. In latter case, you will need to create custom type, or use component mapping.
2. If you don't want to access phone numbers as Phone1, Phone2 and Phone3, but rather want to have a collection (list, for example) of numbers, then after you "Contact" class will be instantiated and filled with data, you can take three separated members with phone numbers and manually create a collection with numbers.

_________________
Best,
Andrew Mayorov // BYTE-force


Top
 Profile  
 
 Post subject: CompositeUserType
PostPosted: Thu Feb 09, 2006 1:01 am 
Regular
Regular

Joined: Tue Jan 03, 2006 7:21 am
Posts: 85
Here is how you can solve this by using CompositeUserType

Create a new Custom User Type by implementing the ICompositeUserType interface and implement all the relevant methods. Specify your mapping as
Code:
<property name="PhoneNumbers" type="DAL.PhoneType, DAL">
         <column name="Phone1"/>
         <column name="Phone2"/>
         <column name="Phone3"/>
      </property>

In the NullSafeGet method return an ArrayList of your PhoneNumber class:
Code:
public Object NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
      {
         String first = (String) NHibernateUtil.String.NullSafeGet(rs, names[0], session, owner);
         String second = (String) NHibernateUtil.String.NullSafeGet(rs, names[1], session, owner);
         String third = (String) NHibernateUtil.String.NullSafeGet(rs, names[2], session, owner);

         ArrayList lst = null;
         if (first!=null && second!=null && third!=null)
         {
            lst = new ArrayList(3);
            lst.Add(new PhoneNumber(first));
            lst.Add(new PhoneNumber(second));
            lst.Add(new PhoneNumber(third));
         }
         return lst;
      }


Your Contact class would look like this:

Code:
public class Contact
   {
      private string _AccountNo;

      private IList _PhoneNumbers;

      public virtual string id
      {
         set{ _AccountNo = value; }
         get{ return _AccountNo; }
      }

      public virtual IList PhoneNumbers
      {
         set{ _PhoneNumbers = value; }
         get{ return _PhoneNumbers; }
      }
      public Contact()
      {
         //
         // TODO: Add constructor logic here
         //
      }
   }


Hope this helps.......


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 09, 2006 4:29 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
Very good solution, samujob!

_________________
Best,
Andrew Mayorov // BYTE-force


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 09, 2006 5:33 am 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
yes, i learned something new as well.. thank you!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 09, 2006 9:19 am 
Newbie

Joined: Mon Jan 30, 2006 10:53 pm
Posts: 7
Thanks Samujob, that looks great! I'm going to try it out later today.


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