-->
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.  [ 14 posts ] 
Author Message
 Post subject: Mapping collections of Joined-subclasses?
PostPosted: Fri Jul 21, 2006 3:49 pm 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
How straight forward is it to map something like the following sitation?

(another explanation of this exact problem can be found in this thread: http://forum.hibernate.org/viewtopic.php?t=941990 see the post by dtabuenc )

I have 1 Type Hiearchy as follows:

Parent is a super class. Person and Org are joined-subclasses.
Code:
Parent(abstract)|->Person
                |->Org

This is straightforward and I have mapped this fine.

I also have this super, sub situation as above (joined-subclass):
Code:
Contact(abstract)->Address
                 ->Phone
                 ->Electronic


Again, this part is easy to map. Where I am unsure, is in how I would map a one-to-many where a Person( or any subclass of Party) would have a collection of PostalAddress and a collection of Phone etc.

Parent would connect to Address, Phone through the Contact table. I guess the tricky part is that i want a seperate collection for each Contact subtype not a collection of Contacts. I don't know how to map this so that NHibernate knows it needs to go through the Contact mapping to get the appropriate sub types. How would I go about mapping such a relationship?



Thanks,
Christian[/url]


Last edited by ChristianD on Mon Jul 24, 2006 3:23 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 10:24 am 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
Is this not possible?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 11:00 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
It should be pretty straightforward, just use <set><one-to-many class="Address" /></set> and <set><one-to-many class="Phone" /></set>, etc.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 11:16 am 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
Sergey,

THat doesn't work. I have the following.
(another explanation of this exact problem can be found in this thread: http://forum.hibernate.org/viewtopic.php?t=941990 see the post by dtabuenc )

Code:
<set name="ElectronicAddresses" lazy="true" >
      <key column="contactid"/>
      <one-to-many class="Demo.ElectronicAddress"/>
   </set>


I captured the query in SQL Server profiler and NHibernate passes the personid value as the contactid. It's missing the join through the Contact table.

Nhibernate needs to create a query like:
Code:
select <fields> from person a
join contact b on a.personid = b.personid
join ElectronicAddress c on b.contactid = c.contactid
where a.personid = ?


Make sense? Am i missing something?

edit: added mapping files
Code:
<class name="Parent" table="Parent" >
   <id name="Id" column="ParentId" type="Int32">
      <generator class="identity"/>
   </id>
   <property name="ActiveDate" column="FromDate" type="Date"/>
   <set name="ElectronicAddresses"  lazy="true" order-by="contactmechanismid" inverse="true">
      <key column="contactmechanismid" />
      <one-to-many class="Demo.ElectronicAddress, Demo"/>
   </set>
    <joined-subclass name="Person" table="Person" >
      <key column="ParentId"/>
         <property name="FirstName" type="String"/>
         <property name="LastName" type="String"/>
   </joined-subclass>

Code:

<class name="Contact" table="Contact" >
   <id name="Id" column="ContactID" type="Int32">
      <generator class="identity"/>
   </id>
   <property name="ActiveDate" column="FromDate" type="Date"/>
   <joined-subclass name="ElectronicAddress" table="ElectronicAddress" >
      <key column="ContactID"/>
      <property name="AddressString" type="String"/>
</joined-subclass>
</class>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 2:06 pm 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
I guess it would be fair to assume this isn't possible?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 3:22 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Hmm, if Gavin says it's not possible in the linked post then the answer has got to be the same for NHibernate...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 3:32 pm 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
That's disappointing. I imagine there is a pattern to deal with this situation. Any insights? I might have to ditch NHibernate, which is too bad.

Christian


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 5:45 am 
Senior
Senior

Joined: Wed Jun 15, 2005 4:17 am
Posts: 156
ChristianD wrote:
That's disappointing. I imagine there is a pattern to deal with this situation. Any insights? I might have to ditch NHibernate, which is too bad.


Be flexible and creative! Hibernate is just a tool, and every tool has limitations! If you can't map the collections easily, you can always build a method in some Dao class which will return the results from a HQL query or even a SQL query. So you can have:

Code:
class ContactDao
{
...
IList GetAddresses(Contact contact) {...}
IList GetPhones(Contact contact) {...}
IList GetEmails(Contact contact) {...}
...
}


another approach: have a polymorphic collection in your Parent base class of Contact objects. This is straightforward to map. Add methods to your Parent class which return what you want: Address, Phone collections by filtering the existing mapped collection of Contact objects. When the collection filtering from Hibernate 3 will be ported to NHibernate I think will be trivial to do this.

HTH,
radu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 11:39 am 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
THanks radu. I have gone down that path. I am having a problem though. I am attempting to implement it as:

Code:
Public Property Contacts() As IList
        Get
            Return _contacts
        End Get
        Set(ByVal Value As IList)
            _contacts = Value
        End Set
    End Property

    Public Property ElectronicAddresses() As IList
        Get
            If _electronicAddressesLoaded Then
                Return Me._electronicAddresses
            Else
                Return Me.GetElectronicAddresses()
            End If
        End Get
        Set(ByVal Value As IList)
            Me._contacts = Value
        End Set
    End Property

    Private Function GetElectronicAddresses()
        Dim temp As IList
        _electronicAddressesLoaded = True
        For Each item As Contact In Me.Contacts
            If item.GetType Is GetType(ElectronicAddress) Then
                _electronicAddresses.Add(item)
            End If
        Next
    End Function


THe mapping looks like this:
Code:
<bag name="Contacts" lazy="true" order-by="contactid">
      <key column="partyid" />
      <one-to-many class="Demo.Contact, Demo"/>
   </bag>


I am getting the following error:
"Cannot instantiate abstract class or interface: Demo.Contact"

I am obviously not an expert when it comes to OO stuff :)

Thanks,
Christian


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 11:48 am 
Senior
Senior

Joined: Wed Jun 15, 2005 4:17 am
Posts: 156
check that for every row in the table which maps the Contact base class there is a corresponding entry in the tables for the derived classes. If there is an "orphan" row in the Contact table this means that hibernate will try to instantiate a Contact object, hence the error.

Radu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 11:56 am 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
Ok, so if i only have say to of the 3 subtypes implemented NHIbernate will do this? There are actually 3 subtypes. I only created 2 as i am protoyping. Will this cause NHibernate to throw this error?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 12:02 pm 
Senior
Senior

Joined: Wed Jun 15, 2005 4:17 am
Posts: 156
No, it shouldn't. Have you checked the data in your tables? If you have rows in Contact table whithout corresponding rows in one of the already mapped subclasses the error will manifest. For testing purposes you can remove the abstract qualifier from the Contact base class. Don't forget to provide a default constructor even if its private.

Radu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 12:16 pm 
Newbie

Joined: Tue Apr 25, 2006 5:20 pm
Posts: 17
There are no orphaned rows, I just checked. Is there anything else that might cause this?

radu wrote:
No, it shouldn't. Have you checked the data in your tables? If you have rows in Contact table whithout corresponding rows in one of the already mapped subclasses the error will manifest. For testing purposes you can remove the abstract qualifier from the Contact base class. Don't forget to provide a default constructor even if its private.

Radu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 26, 2006 12:18 pm 
Senior
Senior

Joined: Wed Jun 15, 2005 4:17 am
Posts: 156
from hibernate point of view they can be orphaned if you mapped only 2 of the 3 tables. The rows corresponding for the 3rd table are seen as orphans as you didn't map the subclass.

Radu


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