CMP 2.0 entity bean classes are defined using abstract accessor methods that represent virtual persistence and relationship fields. As you learned in Chapter 6, Chapter 7, and Chapter 8, the actual fields themselves are not declared in the entity classes. Instead, the characteristics of these fields are described in detail in the XML deployment descriptor used by the entity bean. The abstract persistence schema is the set of XML elements in the deployment descriptor that describe the relationship and persistence fields. Together with the abstract programming model (i.e., the abstract accessor methods) and some help from the deployer, the container tool has enough information to map the entity and its relationships with other entity beans.
The relationships between entity beans are described in the
<relationships>
section of the XML deployment descriptor. The
<relationships>
section falls between the
<enterprise-beans>
and
<assembly-descriptor>
sections. Within the
<relationships>
element, each
entity-to-entity relationship is defined in a separate
<ejb-relation>
element:
<ejb-jar> <enterprise-beans> ... </enterprise-beans> <relationships> <ejb-relation> ... </ejb-relation> <ejb-relation> ... </ejb-relation> </relationships> <assembly-descriptor> ... </assembly-descriptor> </ejb-jar>
Defining
relationship fields requires that an
<ejb-relation>
element be added to the XML
deployment descriptor for each entity-to-entity relationship. These
<ejb-relation>
elements complement the
abstract programming model. For each pair of abstract accessor
methods that define a relationship field, there is an
<ejb-relation>
element in the deployment
descriptor. EJB 2.0 requires that the entity beans in a relationship
be defined in the same XML deployment descriptor.
Here is a partial listing of the deployment descriptor for the Customer and Address EJBs, emphasizing the elements that define the relationship:
<ejb-jar> ... <enterprise-beans> <entity> <ejb-name>CustomerEJB
</ejb-name> <local-home>com.titan.customer.CusomterLocalHome</local-home> <local>com.titan.customer.CustomerLocal</local> ... </entity> <entity> <ejb-name>AddressEJB
</ejb-name> <local-home>com.titan.address.AddressLocalHome</local-home> <local>com.titan.address.AddressLocal</local> ... </entity> ... </enterprise-beans> <relationships> <ejb-relation> <ejb-relation-name>Customer-Address</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name> Customer-has-an-Address </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>CustomerEJB
</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>homeAddress</cmr-field-name> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name> Address-belongs-to-Customer </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>AddressEJB
</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships> </ejb-jar>
All relationships between the Customer EJB and other entity beans,
such as the CreditCard, Address, and Phone EJBs, require that we
define an <ejb-relation>
element to
complement the abstract accessor methods.
Every relationship may have a relationship name, which is declared in
the <ejb-relation-name>
element. This name identifies the
relationship for individuals reading the deployment descriptor or for
deployment tools, but it is not required.
Every <ejb-relation>
element has exactly two
<ejb-relationship-role>
elements, one for each participant in the relationship. In the
previous example, the first
<ejb-relationship-role>
declares the
Customer EJB’s role in the relationship. We know this because
the <relationship-role-source>
element
specifies the <ejb-name>
as
CustomerEJB
. CustomerEJB
is the
<ejb-name>
used in the Customer EJB’s
original declaration in the
<enterprise-beans>
section. The
<relationship-role-source>
element’s
<ejb-name>
must always match an
<ejb-name>
element in the
<enterprise-beans>
section.
The <ejb-relationship-role>
element also
declares the cardinality, or
multiplicity, of the
role. The <multiplicity>
element can be
either One
or Many
. In this
case, the Customer EJB’s
<multiplicity>
element has a value of
One
, which means that every Address EJB has a
relationship with exactly one Customer EJB. The Address EJB’s
<multiplicity>
element also specifies
One
, which means that every Customer EJB has a
relationship with exactly one Address EJB. If the Customer EJB had a
relationship with many Address EJBs, the Address EJB’s
<multiplicity>
element would be set to
Many
.
If the bean described by the
<ejb-relationship-role>
element maintains a
reference to the other bean in the relationship, that reference must
be declared as a container-managed relationship field in the
<cmr-field>
element. The
<cmr-field>
element is declared under the
<ejb-relationship-role>
element:
<ejb-relationship-role> <ejb-relationship-role-name> Customer-has-an-Address </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>CustomerEJB</ejb-name> </relationship-role-source><cmr-field>
<cmr-field-name>homeAddress</cmr-field-name>
</cmr-field>
</ejb-relationship-role>
EJB 2.0 requires that the
<cmr-field-name>
begin with a lowercase letter. For every relationship field defined
by a <cmr-field>
element, the bean class
must include a pair of matching abstract accessor methods. One method
in this pair must be defined with the method name
set<
cmr-field-name
>()
,
with the first letter of the
<cmr-field-name>
changed to uppercase. The
other method is defined as
get<
cmr-field-name
>()
,
also with the first letter of the
<cmr-field-name>
in uppercase. In this
example, the <cmr-field-name>
is
homeAddress
, which corresponds to the
getHomeAddress()
and
setHomeAddress()
methods defined in the
CustomerBean
class:
// bean class code public abstract voidsetHomeAddress
(AddressLocal address); public abstract AddressLocalgetHomeAddress
(); // XML deployment descriptor declaration <cmr-field> <cmr-field-name>homeAddress
</cmr-field-name> </cmr-field>
The <cascade-delete>
element requests
cascade deletion; it can be used with one-to-one or one-to-many
relationships. It is always declared as an empty element:
<cascade-delete/>
.
<cascade-delete>
indicates that the lifetime
of one entity bean in a particular relationship depends upon the
lifetime the other entity bean in the relationship. Here’s how
to modify the relationship declaration for the Customer and Address
EJBs to obtain a cascade delete:
<relationships>
<ejb-relation>
<ejb-relationship-role>
<multiplicity>One</multiplicity>
<role-source>
<ejb-name>CustomerEJB</ejb-name>
</role-source>
<cmr-field>
<cmr-field-name>homeAddress</cmr-field-name>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<multiplicity>One</multiplicity>
<cascade-delete/>
<role-source>
<dependent-name>Address</dependent-name>
</role-source>
</ejb-relationship-role>
</ejb-relation>
</relationships>
With this declaration, the Address EJB will be deleted automatically when the Customer EJB that refers to it is deleted.