Design
Container-managed relationships (CMR) can make it much easier
to build applications where objects are tightly coupled. Such is the case in
the FBS 10g, where each User Account object has one-to-many relationships with Portfolio,
Alert, and Preference objects. To watch a viewlet that shows how the FBS 10g uses
CMR, browse to:
If you're thinking of using CMR, consider these factors as
you design the application:
-
The CMR mechanism uses local interfaces, which require the related objects
to be packaged and deployed in the same ejb.jar file.
-
Bean implementation classes must not declare instance variables. Instead,
they must declare methods to get and set instance variable values. These
methods, known collectively as accessor methods, are generated by
the container provider's tools when the bean is deployed.
-
Implementation classes must be declared abstract. The container
provider's tools will generate the code to implement the relationship in
the accessor methods of the EJB wrapper object.
Relationships are defined declaratively in ejb-jar.xml,
the deployment descriptor file. The following listing shows the part of the
FBS 10g deployment descriptor file that defines the relationship between a user
account and associated preferences.
... <relationships> ... <ejb-relation> <ejb-relation-name>UserAccount-Preferences</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name> UserAccount-has-many-Preferences </ejb-relationship-role-name> <multiplicity>one</multiplicity> <relationship-role-source> <ejb-name>UserAccount</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>preferences</cmr-field-name> <cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name> Preferences-belongs-to-UserAccount </ejb-relationship-role-name> <multiplicity>many</multiplicity> <cascade-delete/> <relationship-role-source> <ejb-name>Preferences</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> ... </relationships> ...
For each <ejb-relation> there are two <ejb-relationship-role>
tags, one for each side of the relationship. Within the <relationship-role-source>
tags, the <ejb-name> tags identify the beans that participate
in the specified relationship. In this example, the relationship cardinality
is one-to-many and the direction is one-way, from UserAccount to
Preferences. Cardinality is defined by <multiplicity>
tags, direction by <cmr-field> tags.
The <multiplicity> tag can have a value
of one or many. To represent a one-to-one relationship,
both <multiplicity> tags in each <ejb-relationship-role>
are set to one.The one-to-one relationship is rare in the RDBMS
world, as this data would typically be normalized into one table. It is more
common in the Object-Oriented (OO) world.
For one-to-many relationships, the bean on the one
side of the relationship (in this example, it's UserAccount) has
the <multiplicity>tag set to one, and the bean
on the many side (Preferences) has the <multiplicity>
tag set to many.
For a many-to-many relationship, both <multiplicity>
tags are set to many. Many-to-many relationships are also
common in the OO world, but for a RDBMS, this relationship would be represented
by three tables, with one table for each end of the relationship, and a third
table as an intersection table. Oracle Containers for J2EE (OC4J) takes care
of the implementation behind the scenes, and generates extra tables in the database
as needed to store relationship information. This is true not just for many-to-many
relationships, but for the other relationships as well. This is because OC4J
does not rely on Foreign Key Constraints being in place.
The <cmr-field> tags define the direction
of the relationship; that is, they specify whether a given bean has access to
the bean at the other end of the relationship. In the listing above, the UserAccount
side of the relationship includes <cmr-field> tags indicating
that a UserAccount has access to a collection of Preferences.
Thus, given a UserAccount bean, you can navigate to the associated
Preferences. There are no <cmr-field> tags on
the Preferences side of the relationship, so you can't navigate
from a Preferences object to a UserAccount. By definition,
then, this is a one-way relationship. In a two-way relationship, both sides
would include <cmr-field> tags.
It is important to get the information in the <relationship-role-source>
and <cmr-field> tags correct. Otherwise, the container will
try to apply the relationship to the wrong beans, and it will fail.
The <cascade-delete/> tag on the Preferences
side specifies that, when a UserAccount is deleted, all related
Preferences are also deleted. This tag is optional, and is used
here because in the FBS 10g, preferences cannot exist without an associated user
account. In a relationship where entities at either end can exist independently
of one another, do not use the <cascade-delete/> tag.
|