As its name indicates, one-table mapping involves a single table, including rows belonging to all classes of the hierarchy. This single table must then have a special column to specify what kind of object is being stored in the rows. This column can bear many names: category, type, kind, class, variety, brand, sort, etc.
Here's the database schema for our RTM database.
Figure 3. One-table mapping database schema
We've introduced the
Category field here, which can hold one of three
values: "B" (base customer), "G" (Gold customer), and "P" (Platinum Customer).
This field is pretty much useless in our business logic, but we still need
to declare it to code the queries, as we'll see shortly. Don't forget to
initialize this field in
ejbCreate(), for the base class and all subclasses.
BaseCustomerBean class sets the field to "B," the
class sets the field to "G," and the
PlatinumCustomerBean class sets the field to "P."
In this kind of table mapping, a single table contains all fields of
all objects in the whole hierarchy. Fields that are not used in a certain
row are simply left
null. For example, the
Charity field is not used by
base and gold customers. This technique does produce a lot of
but it shouldn't be a problem.
locate methods for this table-mapping technique are the same as
in the horizontal mapping, so I'll skip this part.
But there is one problem introduced by this table mapping.
don't behave as they should. Imagine a situation where there's a regular
customer with customer ID of "123." Finding a gold customer using this same
key will return a (wrong) result! There has to be a way to filter out the
other kinds of customers when querying the database. In this example, it
would mean ignoring regular and platinum customers when finding a gold
Working around this problem is easy, in most cases. Just add a condition at the end of every EJB-QL query, like this:
EJB-QL Query for Base customers:
SELECT OBJECT(c) FROM BaseCustomerEJBOneTable AS c WHERE c.category = 'B'
EJB-QL Query for Gold customers
SELECT OBJECT(c) FROM GoldCustomerEJBOneTable AS c WHERE c.category = 'G'
EJB-QL Query for Platinum customers
SELECT OBJECT(c) FROM PlatinumCustomerEJBOneTable AS c WHERE c.category = 'P'
But what about
findByPrimaryKey()? The container writes this method
for you. How do you filter out the unwanted rows? Once more, the only way
to work around this problem is to rely on a feature of your application
WebLogic Server 7 allows overwriting
using a WebLogic-QL query in weblogic-cmp-rdbms-jar.xml.
I'm using this trick in my RTM example.
Other vendors may tackle this in other ways. Some may allow manually writing
this query in ejb-jar.xml, although that may go against the specification.
Some may not support this feature at all, which makes one-table mapping
Assessment: This kind of table mapping is often used with a legacy database, which typically has tables with category columns. It requires that the application server provide a way to filter out the rows that are not wanted when running the queries.
Conclusion and Acknowledgments
I didn't invent any of this. Many products exist out there which allow us to use these three techniques (and others) when mapping database tables to hierarchies of classes. I merely applied the three techniques to the special case of entity beans, working around problems as I went.
I specifically want to credit Apple's Enterprise Object Framework (EOF) toolkit for its ingenuity in this field, which inspired me. EOF is a library and tools to map database tables to straight Java (and Objective-C) objects. The maturity of this framework, its flexibility, and its simplicity should be a model for any persistence services provider.
Also worth highlighting, WebLogic Server 7 provided me with all the features needed in order to implement my work-arounds. Kudos to BEA.
Don't get cranky if I didn't mention your favorite persistence services provider tool. I know there are others out there, I just can't explore them all in these few lines.
Next time, we'll see examples of session beans and message-driven beans that use inheritance.
Emmanuel Proulx is an expert in J2EE and Enterprise JavaBeans, and is a certified WebLogic Server 7.0 engineer. He works in the fields of telecommunications and web development.
Return to ONJava.com.