5.7 Inheritance
You may have one or more inheritance hierarchies in your object
model. JDO implementations provide an assortment of approaches for
mapping the Java classes in an inheritance hierarchy into the
nonhierarchical relational tables. To understand the different
mapping alternatives that are available, consider the inheritance
hierarchy in Figure 5-1.
JDO implementations support one or more of the following mapping
strategies:
Each class in the hierarchy has a separate table. With this approach, a separate table is used for each class: A, B1,
B2, C1, C2, C3, C4. Each table contains only the fields from its
associated class. To access all the fields of a C1 instance,
including the fields inherited from A and B1, it is necessary to
access the tables corresponding to A, B1, and C1. Accessing a B2
instance requires accessing A and B2. With this approach, typically the primary keys for B1 and B2 are
defined as foreign keys on A, the primary keys for C1 and C2 are
defined as foreign keys on B1, and the primary keys for C3 and C4 are
defined as foreign keys on B2. Each class in the hierarchy has a separate table, but inherited
fields are duplicated in the tables for each subclass.
This approach avoids the need to access the tables for A and B1 when
accessing an instance of C1; only C1 needs to be accessed. However,
when you use this mapping strategy, support for
inheritance and
polymorphism
becomes very cumbersome. Accessing an instance of class A requires a
join of all of A's tables. The hierarchy is flattened into a single table containing all the
classes.
This is the default approach used for many JDO implementations. All
of the classes in the hierarchy are placed in one table, which must
have a column for every field of every class in the hierarchy.
Essentially, all of the classes in a hierarchy are merged into one
table. This approach relies on the datastore's
efficient storage-management support of null fields, since a row for
an instance of C2 will not use the fields of C1, B2, C3, and C4. With this approach, the JDO implementation uses an additional
type-discriminator
column that has a unique value for each class
stored in the table. When you retrieve the values for an instance,
the value of this column determines the class of the instance to be
constructed. Combination of separate classes and flattened hierarchy. This approach combines fields from multiple classes into a number of
tables, but the mapping between classes and tables is not one to one.
For example, suppose you define three tables: A, B1, and B2. Table A contains the primary key, a type-discriminator column, and
all the fields declared in class A. Table B1 contains a primary key that is also a foreign key to table
A, and columns for each field in classes B1, C1, and C2. Table B2 contains a primary key that is also a foreign key to table
A, and columns for each field in classes B2, C3, and C4.
Leaves of the hierarchy determine the tables. This approach results in four tables, corresponding to the C1, C2,
C3, and C4 classes. But there may also be instances of A, B1, and B2.
The classes are grouped, by default, into the following tables: Table 1 contains the data for the A, B1, and C1 classes. Table 2 contains the data for the C2 class. Table 3 contains the data for the B2 and C3 classes. Table 4 contains the data for the C4 class.
A vendor may support one or more of these inheritance-mapping
approaches. All of the approaches are vendor-specific; JDO does not
standardize inheritance-mapping. Each approach has performance
implications, since an instance's field values may
be spread among several tables that must be joined and accessed. If a
vendor supports more than one inheritance-mapping approach, the
vendor usually will have a metadata extension that
you can use to specify which approach to use. As you can imagine,
only one approach can be used for each inheritance hierarchy.
For a class in an inheritance hierarchy, when the fields of an
instance are mapped to multiple tables, the columns containing the
instance's identity value need to exist in each
table used to represent the class. So, when you use the first
inheritance-mapping approach, an instance of C1 has the same
primary-key value in the tables that correspond to classes A, B1, and
C1. Some implementations let you specify the names of the primary-key
columns for each table used in the inheritance hierarchy.
|