-->
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.  [ 2 posts ] 
Author Message
 Post subject: Having difficulty mapping an association class
PostPosted: Thu Feb 09, 2006 5:01 am 
Newbie

Joined: Wed Feb 08, 2006 10:51 pm
Posts: 1
I'm a new NHibernate user (v 1.0.2.0) and have been trying to learn how to use it.

It's been going OK, but I've hit a hurdle. Our relational model has a join table between two entities that has additional columns I would like to use. I've tried two approaches to mapping this, and scoured the Hibernate documentation for examples without any luck.

I have the following tables (only pertinent fields are listed):
Organizations
Code:
OrganizationId (PK)


Contacts
Code:
ContactId (PK)


OrganizationContact
Code:
OrganizationId [PK]
ContactId [PK]
BusinessPhoneNumber
Position


Our model states that contacts may be members of one or more organizations and each organization may have one or more contacts. Each contact in an organization has a position and a business telephone number.


The object model looks like:
Organization
Code:
public class Organization {
   private int organizationId;
   private IList contactRoles;
   //...

   public int OrganizationId {
      get { return organizationId; }
      set { organizationId = value; }
   }
   public IList ContactRoles {
      get { return contactRoles; }
      set { contactRoles= value; }
   }
   //...
}


Contact
Code:
public class Contact {
   private int contactId;
   private IList organizationRoles;
   //...

   public int ContactId{
      get { return contactId; }
      set { contactId= value; }
   }
   public IList OrganizationRoles{
      get { return organizationRoles; }
      set { organizationRoles= value; }
   }
   //...
}


OrganizationContact
Code:
public class OrganizationContact {
   private string position;
   private string businessPhone;
   private Contact contact;
   private Organization organization;

   public string Position {
      get { return position; }
      set { position = value; }
   }
   public string BusinessPhone {
      get { return businessPhone; }
      set { businessPhone = value; }
   }
   public Contact Contact {
      get { return contact; }
      set { contact = value; }
   }
   public Organization Organization {
      get { return organization; }
      set { organization = value; }
   }
}



My first attempt to map this was to create a one-to-many association between Organization and OrganizationContact and Contact and OrganizationContact. So I created 3 mappings:
Organization.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Test.Organization, Test" table="Organizations">
      <id name="OrganizationId" column="OrganizationId" type="Int32" length="4" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <!-- ... -->
      <bag name="ContactRoles" lazy="true" inverse="true">
         <key column="OrganizationId"/>
         <one-to-many class="Test.OrganizationContact, Test"/>
      </bag>
   </class>
</hibernate-mapping>


Contact.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Test.Contact, Test" table="Contacts">
      <id name="ContactId" column="ContactId" type="Int32" length="4" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <!-- ... -->
      <bag name="OrganizationRoles" lazy="true" inverse="true">
         <key column="ContactId"/>
         <one-to-many class="Test.OrganizationContact, Test"/>
      </bag>
   </class>
</hibernate-mapping>


OrganizationContact.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Test.OrganizationContact, Test" table="OrganizationContacts">
      <id name="OrganizationContactId" column="OrganizationContactId" type="Int32" length="4" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <property name="Position" />
      <property name="BusinessPhone" />
      <many-to-one name="Contact" column="ContactId" cascade="save-update" class="Test.Contact, Test" />
      <many-to-one name="Organization" column="OrganizationId" cascade="save-update" class="Test.Organization, Test" />
   </class>
</hibernate-mapping>



This all seemed to be OK (at least I wasn't getting any mapping errors) when loading my assembly. The problems arose when I tries to save an OrganizationContact. It would save OK and persist any associated Contact and Organization objects:

Code:
Contact contact = new Contact();
...
Organization organization = new Organization();
...

OrganizationContact organizationContact = new OrganizationContact();
organizationContact.BusinessPhone = "1234 5678";
organizationContact.Position = "Assistant Co-Chief Inspector of Bottle Caps";
organizationContact.Contact = contact;
organizationContact.Organization = organization;

Session.Save(organizationContact);


However, when I later tried to load an Organization or Contact that had an association via OrganizationContact, the Contact.OrganizationRoles or Organization.ContactRoles collections were always null:
Code:
Contact contact = (Contact) ISession.Get(typeof(Contact), 123);
int count = contact.OrganizationRoles.Count;   // <-- throws a NullReferenceException



I went on a search for information and found a post in this forum that suggested reading up on "Collections of dependent objects" in the Hibernate documentation. To that end I changed the mapping files as follows:

Organization.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Test.Organization, Test" table="Organizations">
      <id name="OrganizationId" column="OrganizationId" type="Int32" length="4" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <!-- ... -->
      <bag name="ContactRoles" table="OrganizationContacts" lazy="true">
         <key column="OrganizationId"/>
         <composite-element class="Test.OrganizationContact, Test">
            <property name="Position" />
            <property name="BusinessPhone" />
            <many-to-one name="Contact" class="Test.Contact, Test" />
         </composite-element>
      </bag>
   </class>
</hibernate-mapping>


Contact.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="Test.Contact, Test" table="Contacts">
      <id name="ContactId" column="ContactId" type="Int32" length="4" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <!-- ... -->
      <bag name="OrganizationRoles" table="OrganizationContacts" lazy="true">
         <key column="ContactId"/>
         <composite-element class="Test.OrganizationContact, Test">
            <property name="Position" />
            <property name="BusinessPhone" />
            <many-to-one name="Organization" class="Test.Organization, Test" />
         </composite-element>
      </bag>
   </class>
</hibernate-mapping>


OrganizationContact.hbm.xml
This mapping was removed.


Now when I try to load an Organization I get an error. In the Hibernate log file there's an SQL error: Incorrect syntax near the keyword 'Contact'. This is as a result of executing the following generated SQL statement (reformmatted for easier reading):
Code:
SELECT   OU.OrganizationId as Organiza5___
   , OU.Position as Position__
   , OU.BusinessPhone as Business3___
   , OU.Contact as Contact__
   , C.ContactId as ContactId0_
   , C.EmailAddress as EmailAdd4_0_
   , C.Mobile as Mobile0_
   , C.PostalAddress1 as PostalA16_0_
   , C.PostalAddress2 as PostalA17_0_
   , C.StreetAddressSuburb as StreetA12_0_
   , C.Password as Password0_
   , C.PostalAddressCountry as PostalA21_0_
   , C.StreetAddressCountry as StreetA15_0_
   , C.StreetAddress1 as StreetA10_0_
   , C.FirstName as FirstName0_
   , C.StreetAddress2 as StreetA11_0_
   , C.StreetAddressPostcode as StreetA14_0_
   , C.PostalAddressPostcode as PostalA20_0_
   , C.LastName as LastName0_
   , C.Title as Title0_
   , C.StreetAddressState as StreetA13_0_
   , C.Phone as Phone0_
   , C.Fax as Fax0_
   , C.PostalAddressState as PostalA19_0_
   , C.PostalAddressSuburb as PostalA18_0_
FROM   OrganizationContacts OU
left outer join
   Contacts C on OU.Contact=C.ContactId
WHERE OU.OrganizationId = @p0



I don't know what to do. I'm not sure why the original version isn't working correctly and I can see that the 2nd mapping attempt is incorrectly thinking that a Contact column exists in OrganizationContacts, but I'm not sure why!

Sorry for the massive post, I just wanted to provide as much information as I could. Any help would really be appreciated. Apart from this snag, my forays into NHibernate are going really well. I just can't work this one out.


Top
 Profile  
 
 Post subject: Lazy setting
PostPosted: Thu Feb 09, 2006 5:13 am 
Regular
Regular

Joined: Tue Jan 03, 2006 7:21 am
Posts: 85
In your first approach I see that you have defined the bags to be lazy. Now for this to work you need to also specify all the properties of OrganizationContact as virtual.

Try this and see if the first approach works (i.e. can you now do int count = contact.OrganizationRoles.Count;)


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