Forum OpenACS Q&A: Response to Apple WebObjects
With vertical mapping, a subclass can be added at any time without
modifying the Person table. Existing subclasses can also be modified
without affecting the other classes in the class hierarchy. The primary
virtue of this approach is its clean, normalized design.
Vertical mapping is the least efficient of all of the approaches. Every layer
of the class hierarchy requires a join to resolve the relationships. For
example, if you want to do a deep fetch from Person, three fetches are
performed: a fetch from Employee (with a join to Person), a fetch from
Customer (with a join to Person), and a fetch from Person to retrieve all
the Person attributes. (If Person is an abstract superclass for which no
objects are ever instantiated, the last fetch is not performed.)
In this approach, you have separate tables for Employee and Customer
that each contain columns for Person. The Employee and Customer
tables contain not only their own attributes, but all of the Person
attributes as well. If instances of Person exist that are not classified as
Employees or Customers, a third table would be required (where Person
is not an abstract class). In other words, with horizontal mapping every
concrete class has a self-contained database table that contains all of the
attributes necessary to instantiate objects of the class.
Similar to vertical mapping, a subclass can be added at any time without
modifying other tables. Existing subclasses can also be modified
without affecting the other classes in the class hierarchy.
This approach works well for deep class hierarchies, as long as the fetch
occurs against the leaves of the class hierarchy (Employee and Customer)
rather than against the root (Person). In the case of a deep fetch, it's more
efficient than vertical mapping (since no joins are performed). It's the
most efficient approach, if you only fetch instances of one leaf subclass
at a time.
Problems may occur when attributes need to be added to the Person
superclass. The number of tables that need to be altered is equal to the
number of subclasses'the more subclasses you have, the more effort
is required to maintain the superclass. However, if table maintenance
happens far less often than fetches, this might be a viable approach for
Single Table Mapping
In this approach, you put all of the data in one table that contains all
superclass and subclass attributes. Each row contains all of the columns
for the superclass as well as for all of the subclasses. The attributes that
don't apply for each object have NULL values. You fetch an Employee
or Customer by using a query that just returns objects of the specified
type (the table would probably include a type column to distinguish
records of one type from the other).
This approach is faster than the other two methods for deep fetches.
Unlike vertical or horizontal mapping, you can retrieve superclass objects
with a single fetch, without performing joins. Adding a subclass or
modifying the superclass requires changes to just one table.
Single table mapping can consume an inordinate amount of space since
every row includes columns for every one of the other entities' attributes.
This may depend on how your database stores NULLs. Some databases
condense NULL values, thereby reducing the storage space needed, but
some databases maintain the length of the actual data type of the column
regardless of the value stored. Most databases also have limitations
on how many columns a table can have (typically this is around
250 columns), which can make it impossible to use single table
mapping for a deep class hierarchy that has lots of instance variables.
Also, if you have a lot of data, this approach can actually be less efficient
than horizontal mapping since with single table mapping you have to
search the entire table to find the rows needed to instantiate objects
of a particular type. (Horizontal mapping is only more efficient if your
application just fetches one type of leaf object at a time (instances of a
Accessing Multiple Databases
Enterprise Objects Framework applications access multiple databases
almost transparently. Simply make different models for each database,
and then you can create relationships from an entity in one database to an
entity in another. In your application, you can fetch enterprise objects
from different databases into the same object graph without any extra
work. See the chapter Using EOModeler for more information.
However, there are a couple of pitfalls that can occur when you're
working with more than one database:
Enterprise Objects Framework doesn't implement a two-phase
EODatabaseDataSources with models for different databases can
erroneously rendezvous on the same EODatabaseContext.