-->
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.  [ 3 posts ] 
Author Message
 Post subject: Mapping role-player design pattern
PostPosted: Mon Dec 03, 2007 5:43 am 
Beginner
Beginner

Joined: Tue May 17, 2005 2:48 pm
Posts: 47
NHibernate version:
1.2.0

Mapping documents:
<class name="Person" table="tblPerson">
<id name="ID" column="PersonID">
<generator class="identity"/>
</id>
<bag name="Roles" inverse="true">
<key column="PersonID"/>
<one-to-many class="IPersonRole"/>
</bag>
</class>

<class name="Customer" table="tblCustomer" >
<id name="ID" column="CustomerID">
<generator class="identity" />
</id>
</class>

Name and version of the database you are using:
SQL Server 2005

I have a Person object in my domain model which can play multiple roles in the environment. A person can fulfill the customer, employee or vendor contact role in a period of time. This means I cannot use the Person class as a base class for the Customer, Employee and VendorContact classes, because a person can stop being an employee while still being present as a customer for example. This is a common design pattern in object oriented programming.
Now I have a Person classes with a Roles property. The Roles property contains instances of IPersonRole objects. The Customer, Employee and VendorContact classes implement the IPersonRole interface.

The Customer table has a primary key CustomerId which corresponds with the PersonId primary key of the Person table.

I'm wondering how to map this with NHibernate. The mappings are above.

With this mapping I get the error that the IPersonRole interface is not mapped. Which is true, I didn't map the interface into a mapping file, because properties of the interface doesn't match with database columns; the primary keys of the customer, employee and vendor contacts correspond with PersonId in the Person table.

Can anybody help me out?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 03, 2007 4:57 pm 
Expert
Expert

Joined: Fri May 13, 2005 11:13 am
Posts: 292
Location: Rochester, NY
If the set of Role types is static in relation to your end-to-end release cycle, I would suggest mapping each with a separate <one-to-one> relation. This gives you the benefit of being able to add methods to manage specific roles at compile time. But of course it also limits you to those roles.

If you expect to add to the types of roles more often and easily, maybe so that consuming projects won't break if you add a role with a new version of your domain objects, I would suggest reworking your database and mappings for a proper inheritance mapping (table-per-hierarchy or table-per-subclass).

If you want to add to your role types dynamically at run time, I would suggest leaving off inheritance altogether (unless it is to support a class of roles), and make CustomerRole an association between Customer and a new RoleType class.

I would not suggest using a polymorphic collection like the one you have begun devising, first because it won't work without re-engineering the keys, and second because even when it is working, table-per-concrete-class is pretty ugly and it doesn't really give you any benefit over the <one-to-one> mapping described above.

Good move going with the Role pattern here. Lots of folks get stuck on trying to stuff that idea into an inheritance model, which fails for the exact reasons you cite.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 04, 2007 4:56 am 
Beginner
Beginner

Joined: Tue May 17, 2005 2:48 pm
Posts: 47
I did go for the <one-to-one> relationship solution you suggested. Now, the Person class has a association relation to the Customer class. This way, it isn't a pure Role design pattern anymore, because the Person class is directly dependent on the Customer class and all other role classes it'll get in the future. But I guess it's the best I can do with NHibernate without changing the database.

Thanx.


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