Hibernate -using Table per subclass - how to link an existing superclass object to a subclass object
I have a User hibernate class, Clerk class and Consumer class. All these map开发者_开发技巧s 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 Hibernate to link the same user object with this new Consumer object?
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.
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.
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.
精彩评论