TOC Special:Whatlinkshere_Introduction_to_Relational_Descriptors_(ELUG)[Related Topics]
This section provides an overview of relational descriptors, as well as explains the role of inheritance and various types of descriptors in relational projects.
For information on descriptor concepts and features common to more than one type of EclipseLink descriptors, see Introduction to Descriptors.
Relational descriptors describe Java objects that you map to tables in a relational database. You use them in relational projects.
Using relational descriptors in a relational project, you can configure relational mappings.
For more information, see the following:
In a relational project, you can designate the descriptor as an aggregate.
This lets you configure an aggregate mapping to associate data members in the target object with fields in the source object’s underlying database tables.
When you designate a relational descriptor as an aggregate, EclipseLink lets you specify a mapping type for each field in the target class, but defers associating the field with a database table until you configure the aggregate object mapping in the source descriptor. In other words, the target class descriptor defines how each target class field is mapped, but the source class descriptor defines where each target class field is mapped. This lets you share an aggregate object among many parent descriptors mapped to different tables.
When you designate a relational descriptor as an aggregate, you tell EclipseLink that the class will be a target of an aggregate object mapping, and this ensures that the EclipseLink runtime handles the target class as follows:
-
It inserts, updates, and deletes the target class in parallel with its source class.
-
It does not cache the target class on its own; instead, it caches the target class as part of its source class.
-
It does not allow the target class to be read, written, deleted, or registered in a unit of work.
When working with aggregate relational descriptors, consider the following:
For more information, see Configuring a Relational Descriptor as a Class or Aggregate Type.
EclipseLink supports nested aggregates. In the Nested
Aggregates figure, source class HockeyPlayer
is a normal
nonaggregate class descriptor. It owns target class Info
which is
designated as an aggregate. The Info
class itself owns target
classes PersonalInfo
and TeamInfo
which are each designated as
aggregates.
[Figure 26-1]# Nested Aggregates
In EJB 3.0, an aggregate is known as an embeddable. In the EJB 3.0 specification, an embeddable may not contain another embeddable (that is, the EJB 3.0 specification does not support nested aggregates).
However, if you deploy an EclipseLink-enabled EJB 3.0 application with
persistence to OC4J, you can take advantage of an EclipseLink extension
of the EJB 3.0 specification to configure nested embeddables. Note that
if you do so, your application will not be strictly EJB 3.0-compliant.
The Nested Embeddables example shows the classes
from the Nested Aggregates figure, using EJB 3.0
annotations to take advantage of the EclipseLink extension of the EJB
3.0 specification to allow Info
(an embeddable) to own embeddables
TeamInfo
and PersonalInfo
.
[Example 26-1]# Nested Embeddables
public class HockeyPlayer implements Serializable {
private int playerId;
private Info Info;
private String lastName;
private String firstName;
...
@Embedded
public Info getInfo() {
return Info;
}
}
@Embeddable
public class Info implements Serializable {
TeamInfo teamInfo; // EclipseLink extension of EJB 3.0 allows Embeddable with Embeddable
PersonalInfo personalInfo;
public Info() {}
@Embedded
public PersonalInfo getPersonalInfo() {
return personalInfo;
}
public void setPersonalInfo(PersonalInfo personalInfo) {
this.personalInfo = personalInfo;
}
@Embedded
public TeamInfo getTeamInfo() {
return teamInfo;
}
public void setTeamInfo(TeamInfo teamInfo) {
this.teamInfo = teamInfo;
}
}
@Embeddable
public class PersonalInfo implements Serializable {
private int age;
private double weight;
private double height;
...
}
@Embeddable
public class TeamInfo implements Serializable {
private String position;
private int jerseyNumber;
private HockeyTeam hockeyTeam;
...
}
You can configure inheritance for a relational descriptor designated as an aggregate (see Descriptors and Inheritance), however, in this case, all the descriptors in the inheritance tree must be aggregates. Aggregate and class descriptors cannot exist in the same inheritance tree.
Inheritance describes how a derived class inherits the characteristics of its superclass. You can use descriptors to describe the inheritance relationships between classes in your relational projects.
This section includes information on the following topics:
For more information, see Descriptors and Inheritance.
For relational projects, EclipseLink assumes that all of the classes in an inheritance hierarchy have the same primary key, as set in the root descriptor. Child descriptors associated with data source representations that have different primary keys must define the mapping between the root primary key and the local one.
For more information, see Configuring Primary Keys.
In a relational project, you can map your inheritance hierarchy to a single table or to multiple tables. Use these options to achieve the balance between storage efficiency and access efficiency that is appropriate for your application.
In this example, you store classes with multiple levels of inheritance in a single table to optimize database access speeds.
The entire inheritance hierarchy shown in the Nested
Aggregates figure can share the same table, as in the
Inheritance Using a Superclass Table with Optional
Fields figure. The FueledVehicle
and NonFueledVehicle
subclasses can share the same table even though FueledVehicle
has
some attributes that NonFueledVehicle
does not. The
NonFueledVehicle
instances waste database resources because the
database must still allocate space for the unused portion of its row.
However, this approach saves on accessing time because there is no need
to join to another table to get the additional FueledVehicle
information.
As this figure shows, this approach uses a class indicator field. For more information, see How to Specify a Class Indicator.
['Figure 26-2]# Inheritance Using a Superclass Table with Optional Fields
image::inhtable.gif[Inheritance Using a Superclass Table with Optional Fields,title="Inheritance Using a Superclass Table with Optional Fields"]
In this example, you store classes with multiple levels of inheritance in multiple tables to optimize database storage space.
In the inheritance hierarchy shown in the Nested Aggregates figure, for subclasses that require additional attributes, you use multiple tables instead of a single superclass table. This optimizes storage space because there are no unused fields in the database. However, this may affect performance because EclipseLink must read from more than one table before it can instantiate the object. EclipseLink first looks at the class indicator field to determine the class of object to create, then uses the descriptor for that class to read from the subclass tables.
The Inheritance Using Separate Tables for Each
Subclass figure illustrates the EclipseLink implementation of the
FUELEDVHCL
, CAR
, and BICYCLE
tables. All objects are stored
in the VEHICLE
table. FueledVehicle
, Car
, and Bicycle
information are also stored in secondary tables. Note that because the
NonFueledVehicle
class does not hold any attributes or
relationships, it does not need a secondary table.
[Figure 26-3]# Inheritance Using Separate Tables for Each Subclass
image::inhsepar.gif[Inheritance Using Separate Tables for Each Subclass,title="Inheritance Using Separate Tables for Each Subclass"]
Note: In general, using multitable inheritance is inefficient because it can require excessive joins and multiple table fetching. |
If a root or branch inheritance descriptor has subclasses that span multiple tables, you can configure a database view to optimize the performance of queries against the parent descriptor by outer-joining all of the subclass tables. This allows EclipseLink to fetch all of the subclass instances in one query, instead of multiple queries. It also allows queries for the parent class that use cursors or ordering.
By default, EclipseLink executes multiple queries to read in a multiple table inheritance hierarchy, which, in some cases, is the most efficient way to query. In addition, EclipseLink supports querying the inheritance hierarchy using a single outer-join query.
You can also set a database view on the descriptor that outer-joins or unions all of the tables. For more information, see Configuring Multitable Information.
Category:_EclipseLink_User’s_Guide[Category: EclipseLink User’s Guide] Category:_Release_1[Category: Release 1] Category:_Concept[Category: Concept] Category:_ORM[Category: ORM]