CMP entity bean classes are defined using abstract accessor methods that represent virtual persistence and relationship fields. As discussed in Chapter 6, Chapter 7, and Chapter 8, the fields themselves are not declared in the entity classes. Instead, the characteristics of these fields are described in the bean’s deployment descriptor. The abstract persistence schema is the set of XML elements in the deployment descriptor that describe the relationship and persistence fields. By combining the abstract persistence schema with the abstract programming model (i.e., the abstract accessor methods) and a little 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 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 is
intended for people 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
, which 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 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
>( )
, and the first letter of the
<cmr-field-name>
must be 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.