views:

288

answers:

3

Hi,

I have a User hibernate class, Clerk class and Consumer class. All these maps to their own tables in database. The User PK also acts as Clerk's and Consumer's PK.

So now my problem is that if a user is initially a Clerk, he has a record in Users table and Clerks table. If that user wants to become a consumer, I want to link that User's record to the new Consumer's record. So even if I pass the userId to the consumer's record, it treats it as a new User to be persisted and gives a duplicate_key exception. How do I tell Hiernate to link the same user object with this new Consumer object.

Thanks in advance,

-Chandni

A: 

No, you can't. You are trying to implement multiple inheritance. A User cannot be both a Clerk and a Consumer in a language that does not support multiple inheritance. If this is a valid scenario, then you should map using composition rather than inheritance, so that your User class has both Clerk and Consumer child objects, either or both of which could be null.

David M
Thanks for the reply.. I thought the same.. Regarding PK, even I didn't like the concept of sharing PK but has been built in the system and would have taken quite some effort to change the schema and the code.. Same holds true for changing inheritance now to composition.. So is it true that a superclass object can be of only one type of subclass object. In our case, if the clerk wants to become a consumer of the system, then he cannot be mapped to the same user?Thanks for all your help..
Chandni
He cannot be both a clerk and a consumer. You can amend the database to turn him from a clerk into a consumer, but I don't think there is a way to do this via NHibernate.
David M
A: 

With your current implementation, I think that you'll have to delete the actual Clerk and to persist a new Consumer, after having copied the desired attributes (and this makes sense IMO as you can't cast a Clerk into a Consumer and vice versa). If you use a functional key for your User (as you should), this shouldn't be a problem.

Pascal Thivent
A: 

In my experience the best approach is to think of objects and classes first, and then see what hibernate generates out of that.

When stating your in terms of java you have multiple inheritance (which only works a little with interfaces) and mutating type, i.e. your User is first a clerk an later a consumer. Doesn't work this way.

Consider this model instead:

a User has a map of Role-classes to (subclasses of)Roles. Clerk and Consumer are roles. When you let a role have a backreference to the user, the user can work as a delegate to provide the attributes and methods every user has.

In code this would look similar to this: class User { Map,Role> roles;

<T extends Role> T as(<Class<T>> roleClass>){
    return (T) roles.get(roleClass);
}

Should be nice, clean and flexible. And pretty easy to map to a database schema with hibernate.

Jens Schauder