-->
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.  [ 4 posts ] 
Author Message
 Post subject: Inheritance - Base class without primary key
PostPosted: Thu Mar 30, 2006 9:41 pm 
Regular
Regular

Joined: Wed Feb 15, 2006 9:09 pm
Posts: 76
I'm trying to create a class hierarchy where I stick all common table columns into a base class. So I have a base class called "Auditable" that has "modifyTime" and "modifyUserId" properties. Then I extend that with "Expirable" with properties "validFrom" and "validTo". In the base class mapping, I'm getting an XML validation error (it expects the <id> element, but I don't know the primary key property unless it's a concrete class). Am I approaching this the right way?

Hibernate version: 3.1.3

Mapping documents:

<hibernate-mapping>
<class name="Auditable" abstract="true">
<property name="modifyTime" column="modify_time" type="timestamp" generated="always"/>
<property name="modifyUserId" column="modify_user_id"/>
</class>
</hibernate-mapping>

<hibernate-mapping>
<subclass name="Expirable" extends="Auditable" abstract="true">
<property name="validFrom" column="valid_from" type="date" not-null="true" generated="always"/>
<property name="validTo" column="valid_to" type="date"/>
</class>
</hibernate-mapping>

Full stack trace of any exception that occurs:
org.xml.sax.SAXParseException: <Line 8, Column 14>: XML-20148: (Error) Invalid element 'property' in content of 'class', expected elements '[meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id]'.

Name and version of the database you are using: Oracle 10g 10.1.0


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 30, 2006 10:23 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
No. You should be using delegation. Each of your concrete classes in your current hierarchy should only implement Auditable and Expirable intefaces, not extend classes with those names. This is a particularly fundamental instance of when to use delegation instead of inheritance. Nothing is a "kind-of" Auditable: Auditable isn't a thing, so nothing can be a "kind-of" it. Auditable is a property that other things have.

I blame the English language, becuase it uses the verb "to be" too much :) Sure a blackbird "is" black, but not in the same way that it "is" a bird :) Black is just a property of blackbird. A Blackbird java class might extend the bird class, but it's not going to extend a Black class (though it might implement a Black interface).

Back to your question. The concrete classes will contain many-to-one associations to both Auditable and Expirable: that is, they'll contain an AuditableImpl and an ExpirableImpl, and you'll provide methods in each concrete class like this:
Code:
public Date getValidFrom() { return objAuditableImpl.getValidFrom(); }


You will also need primary keys in both of those tables. Otherwise how would you associate other tables to them?


Top
 Profile  
 
 Post subject: Concrete class mapping
PostPosted: Thu Mar 30, 2006 10:47 pm 
Regular
Regular

Joined: Wed Feb 15, 2006 9:09 pm
Posts: 76
I kind of agree with the delegation (and the blackbird metaphor :), but I'm looking for a way to push common columns down into base classes. So from these classes I would extend, say, Expirable into a user account (let's call the class User and the table user):

Code:
CREATE TABLE user (
  user_id VARCHAR(30) PRIMARY KEY,
  user_name VARCHAR(60),
  valid_from DATE NOT NULL,
  valid_to DATE,
  modify_time DATE,
  modify_user_id DATE
);


and then

Code:
public class User extends Expirable
{

  private String id;
  private String name;
  // all other properties in the base class

}


So I'd like to be able to push the valid_from/valid_to/modify_time/modify_user_id columns down into base classes. Am I still approaching it the right way, or is delegation still the best way? I'd rather not have separate tables for the auditable and expirable interfaces/classes, as while they are properties, they're ones that all the tables and classes share, hence the base classes.

It's all about how you design your class hierarchy (or lack thereof ;)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 30, 2006 11:01 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
silvaran wrote:
I'd rather not have separate tables for the auditable and expirable interfaces/classes, as while they are properties, they're ones that all the tables and classes share, hence the base classes.

Isn't that counter-intuitive? It's certainly normalizing, and most people prefer to denormalize. If you have two tables that both have valid_from and valid_to columns, then don't you want to put those into their own table and share its rows between the two "base class" tables?

Given that you don't want that, then I'd guess that the best approach is to set up your java inheritance the way you want it, then explicitly map every class in its entirety, where possible. Don't even use the table-per-subclass inheritance model: it will be table per subclass, you just don't use the joined-subclass tag. Hibernate thinks that all the classes are separate. That way all your tables are unrelated, but your class hierarchy is maintained. I think that that's what you want.


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