Oracle9iAS Containers for J2EE Enterprise JavaBeans Developer's Guide Release 2 (9.0.3) Part Number A97677-01 |
|
This chapter discusses how to develop entity-to-entity relationships. As a developer, you can approach entity relationships from either the EJB development or database development viewpoint.
This chapter starts by discussing entity relationships from the EJB development viewpoint. Next, it demonstrates how the deployment descriptor maps to database tables. If you want to design with the database development viewpoint, skip to "Mapping Relationship Fields to the Database".
This chapter covers the following topics:
The following sections describe what an entity bean relationship can be and how to define them.
Cardinality refers to the number of entity objects on each side of the relationship. Thus, you can define the following types of relationship between EJBs:
In addition, each relationship can be one-way or two-way. This is referred to as the direction of the relationship. The one-way relationship is unidirectional; the two-way relationship is bidirectional. For example, a unidirectional relationship can be from an employee to an address. With the employee information, you can retrieve an address. However, with an address, you cannot retrieve the employee. An example of a bidirectional relationship is with a employee/projects example. Given a project number, you can retrieve the employees working on the project. Given an employee number, you can retrieve all projects that the employee is working on. Thus, the relationship is valid in both directions.
Normally, you use a unidirectional relationship when you want to reuse the target from multiple entities.
You define the cardinality and direction of the relationship between two beans in the deployment descriptor.
A one-to-one relationship is the simplest relationship between two beans. One entity bean relates only to one other entity bean. If our company office contains only cubicles, and only a single employee can sit in each cubicle, then you have a one-to-one relationship: one employee in one designated cubicle. You define a unidirectional definition for this relationship as follows:
employee --> cubicle
However, if you have a cubicle number and want to determine who is assigned to it, you can assign a bidirectional relationship. This would enable you to retrieve the employee and find what cubicle he/she sits in. In addition, you could retrieve the cubicle number and determine who sits there. You define this bidirectional one-to-one relationship as follows:
employee <--> cubicle
In a one-to-many relationship, one object can reference several instances of another. A many-to-one relationship is when many objects reference a single object. For example, an employee can have multiple addresses: a home address and an office address. If you define these relationships as unidirectional from the perspective of the employee, then you can look up the employee and see all of his/her addresses, but you cannot look up an address to see who lives there. However, if you define this relationship as bidirectional, then you can look up any address and see who lives there.
A many-to-many relationship is complex. For example, each employee can be working on several projects. And each projects has multiple employees working on it. Thus, you have a many-to-many cardinality. The direction does not matter in this instance. You have the following cardinality:
employees <--> projects
In a many-to-many relationship, many objects can reference many objects. This cardinality is the most difficult to manage.
Here are the restrictions imposed on defining your relationships:
The following are the requirements to define each cardinality type and its direction:
get
/set
methods) for each relationship field. The naming follows the same rules as for the persistence field abstract accessor methods. For example, getAddress and setAddress methods are abstract accessor methods for retrieving and setting an address.
<cmr-field-name>
element. This name must be the same as the abstract accessor methods, without the get/set
and the first letter in lower case. For example, the <cmr-field-name>
would be address
to compliment the getAddress/setAddress
abstract accessor methods.
Each relationship field must have the abstract accessor methods defined for it. In a relationship that sets or retrieves only a single entity, the object type passed back and forth must be the local interface of the target entity bean. In a relationship that sets or retrieves multiple objects, the object type passed back and forth is a Set
or Collection
containing local interface objects.
In this example, the employee can have only a single address, and you can retrieve the address only through the employee. This defines a one-to-one relationship that is unidirectional from the perspective of the employee. Then the abstract accessor methods for the employee bean are as follows:
public AddressLocal getAddress(); public void setAddress(AddressLocal address);
Because the cardinality is one-to-one, the local interface of the address entity bean is the object type that is passed back and forth in the abstract accessor methods.
The cardinality and direction of the relationship are defined in the deployment descriptor.
If the employee example included a one-to-many relationship, the abstract accessor methods would pass back and forth a Set
or Collection
of objects, each of which contains target bean local interface objects. When you have a "many" relationship, multiple records are being passed back and forth.
A department contains many employees. In this one-to-many example, the abstract accessor methods for the department retrieves multiple employees. Thus, the abstract accessor methods pass a Collection
or a Set
of employees, as follows:
public Collection getDeptEmployees(); public void setDeptEmployees(Collection deptEmpl);
You define the relationships between entity beans in the same deployment descriptor the entity beans are declared. All entity-to-entity relationships are defined within the <relationships>
element and you can define multiple relationships within this element. Each specific entity-to-entity relationship is defined within an <ejb-relation>
element. The following XML demonstrates two entity-to-entity relationships defined within an application:
<relationships> <ejb-relation> ... </ejb-relation> <ejb-relation> ... </ejb-relation> </relationships>
The following XML shows the full element structure for relationships:
<relationships> <ejb-relation> <ejb-relation-name> </ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name> </ejb-relationship-role-name> <multiplicity> </multiplicity> <relationship-role-source> <ejb-name> </ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name> </cmr-field-name> <cmr-field-type> </cmr-field-type> </cmr-field> </ejb-relationship-role> </ejb-relation> </relationships>
Table 4-1 describes the usage for each of these elements.
Table 4-1 Description of Relationship Elements of the Deployment Descriptor
These relationships can be one-to-one, one-to-many, or many-to-many. The cardinality is defined within the <multiplicity>
element. Each bean defines its cardinality within its own relationship. For example,
<multiplicity>
of one, and the address bean is declared with a <multiplicity>
of one.
<multiplicity>
of one, and the employee bean is declared with a <multiplicity>
of many. For many employees to belong to a department, you define the same <multiplicity>
.
<multiplicity>
of many, and the project is declared with a <multiplicity>
of many.
The direction of the relationship is defined by the presence of the <cmr-field>
element. The reference to the target entity is defined within the <cmr-field>
. If you are unidirectional, then only one entity within the relationship contains a reference to a target. In this case, the <cmr-field>
is declared in the source entity and contains the target bean reference. If bidirectional, both entities should declare each other's target bean references within a <cmr-field>
element.
The following demonstrates how to declare direction in the one-to-one employee and address example:
<cmr-field>
element within the employee bean section that references the address bean. Do not define a <cmr-field>
element in the address bean section of the relationship.
<cmr-field>
element in the employee bean section that references the address bean. In addition, define a <cmr-field>
element in the address bean section that references the employee bean.
Once you understand how to declare the cardinality and direction of the entity relationships, configuring the deployment descriptor for each relationship is simple.
The employee example defines a one-to-one unidirectional relationship in which each employee has only one address. This relationship is unidirectional because you can retrieve the address from the employee, but you cannot retrieve the employee from the address. Thus, the employee object has a relationship to the address object.
In the deployment descriptor, you configure the following:
<entity>
elements within the <enterprise-beans>
section for each of the entity beans involved in the relationship. For this example, these include an <entity>
element for the employee with an <ejb-name>
of EmpBean
and an <entity>
element for the address with an <ejb-name>
of AddressBean.
<ejb-relationship>
element within the <relationships>
section for the one-to-one relationship that contains the following:
<ejb-relationship-role>
element for the employee bean that defines its cardinality as "one" in its <multiplicity>
element. The <relationship-role-source>
element defines the <ejb-name>
as EmpBean
, which is the same name in the <entity>
element.
<ejb-relationship-role>
element for the address bean that defines its cardinality as "one" in its <multiplicity>
element. The <relationship-role-source>
element defines the <ejb-name>
as AddressBean
, which is the same name in the <entity>
element.
<cmr-field>
element in the EmpBean
relationship that points to the AddressBean
. The <cmr-field>
element defines address
as the AddressBean
reference. This element name matches the get and set method names, which are named getAddress
and setAddress
. These methods identify the local interface of the address entity bean as the data type that is returned from the get method and passed in on the set method.
<enterprise-beans> <entity> ... <ejb-name>EmpBean
</ejb-name> <local-home>employee.EmpHome</local-home> <local>employee.Emp</local> <ejb-class>employee.EmpBean</ejb-class> ... </entity> <entity> ... <ejb-name>AddressBean
</ejb-name> <local-home>employee.AddressHome</local-home> <local>employee.Address</local> <ejb-class>employee.AddressBean</ejb-class> ... </entity> </enterprise-beans> ... <relationships> <ejb-relation> <ejb-relation-name>Emp-Address</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Emp-has-Address </ejb-relationship-role-name><multiplicity>One</multiplicity>
<relationship-role-source><ejb-name>EmpBean
</ejb-name> </relationship-role-source> <cmr-field><cmr-field-name>address</cmr-field-name>
</cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name>Address-has-Emp </ejb-relationship-role-name><multiplicity>One</multiplicity>
<relationship-role-source><ejb-name>AddressBean
</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships>
When you have relationships between entity beans and the master entity bean is deleted, what happens to the slave beans? This question is answered by the cascade delete option. If you specify cascade delete to happen, the deletion of a master entity causes the deletion of all its slave relationship entity beans.
The cascade delete is defined in the object that is deleted automatically.
For example, an employee has a relationship with an address object. The employee object specifies cascade delete. When the employee, as master in this relationship, is deleted, the address, the slave, is also deleted.
In some instances, you do not want a cascade delete to occur. If you have a department that has a relationship with multiple employees within the department, you do not want all employees to be deleted when you delete the department.
You can only specify a cascade delete on a relationship if the master entity bean has a <multiplicity>
of one. Thus, in a one-to-one, the master is obviously a "one". You can specify a cascade delete in a one-to-many relationship, but not in a many-to-one or many-to-many relationship.
The cascade delete is specified in the slave entity bean of the one-to-one or one-to-many relationship. Thus, when the master entity bean is deleted, the slave entity beans are deleted.
The following deployment descriptor shows the definition of a one-to-one relationship with the employee and his/her address. When the employee is deleted, the slave entity bean--the address--is automatically deleted. You ensure the deletion by specifying the <cascade-delete/>
element in the slave entity bean of the relationship. In this case, specify the <cascade-delete/>
element in the AddressBean
definition.
<relationships> <ejb-relation> <ejb-relation-name>Emp-Address</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Emp-has-Address
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source><ejb-name>EmpBean</ejb-name>
</relationship-role-source>
<cmr-field>
<cmr-field-name>address</cmr-field-name>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>Address-has-Emp
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<cascade-delete/>
<relationship-role-source><ejb-name>AddressBean</ejb
-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships>
Each entity bean maps to a table in the database. Each of its persistent and relationship fields are saved within a database table in columns. For these fields to be mapped to a database, do one of the following:
orion-ejb-jar.xml
file. See "Explicit Mapping of Relationship Fields to the Database" for more information.
Note: This section discusses how OC4J maps relationship fields to the database. Chapter 3, "CMP Entity Beans" discusses persistent field mapping. |
If you declare relationship fields only in the ejb-jar.xml
file, then OC4J provides default mappings of these fields to the database. The default mapping is the same as for the persistent fields, as described in "Default Mapping of Persistent Fields to the Database". describes.
In summary, these defaults include:
<ejb-name>
in the deployment descriptor.
jar
extension. However, all dashes (-) and periods (.) are converted to underscores (_) to follow SQL conventions. For example, if the name of your JAR file is employee.jar
, then employee_jar
is appended to the name.
If the constructed name is greater than thirty characters, the name is truncated at twenty-four characters. An underscore and then five characters made up of an alphanumeric hash code is appended to the name for uniqueness.
For example, if the EJB name is EmpBean
, the JAR file is empl.jar
, and the application name is employee
, then the default table name is EmpBean_empl_jar_employee
.
<cmp-field>
and <cmr-field>
elements declared in the deployment descriptor. Each <cmp-field>
is a column that relates to the entity bean data. Each <cmr-field>
element represents a relationship. To establish a unidirectional relationship, only a single entity in the relationship defines a <cmr-field>
in the deployment descriptor. To define a bidirectional relationship, both entities in the relationship define a <cmr-field>
.
For each <cmr-field>
element, the container creates a foreign key that points to the primary key of the relevant object, as follows:
The translation rules for converting Java data types to database data types are defined in the specific database XML file located in j2ee/home/config/database-schemas
, such as oracle.xml
.
java.lang.Object
as the primary key class type in <prim-key-class>
, but do not specify the primary key name in <primkey-field>
, then the primary key is auto-generated by the container.
The one-to-one entity relationship is managed between the entity tables with a foreign key. Figure 4-1 demonstrates a one-to-one unidirectional relationship between the employee and address bean.
empl.jar
and the application name is employee
, then the table names are EmpBean_empl_jar_employee
and AddressBean_empl_jar_employee
.
<cmp-field>
and <cmr-field>
elements declared in the deployment descriptor.
EmpBean
table are empno
, empname
, and salary
. A foreign key is created called address
, from the <cmr-field>
declaration, that points to the primary key column of the AddrBean
table.
AddressBean
table are an auto-generated long primary key and columns for stree, city, state, and zip.
empno
. The AddressBean
is configured for an auto-generated primary key by specifying only <primkey-class>
of java.lang.Object
.
You cannot facilitate the one-to-many and many-to-many relationships using only a primary key and foreign key in the entity tables. To facilitate these relationships, the container creates an association table. The association table contains two columns, where each contains a foreign key to each of the entity tables in the relationship.
Figure 4-2 shows the tables that are created for the employee/project relationship. Each project can have multiple employees, and each employee can belong to several projects. Thus, the employee and project relationship is a many-to-many relationship. The container creates three tables to manage this relationship: the employee table, the project table, and the association table for both of these tables.
The association table contains a foreign key column that points to the employee table and a foreign key column that points to the project table. The column names of the association table are a concatenation of the entity bean name in <ejb-name>
and its primary key name. If the primary key for the bean is auto-generated, then "autoid
" is appended as the primary key name. For example, the foreign key that points to the employee table is the bean name of EmpBean
, followed by the primary key name of empno
, which results in the column name EmpBean_empno
. The foreign key that points to the address table is the bean name of ProjectBean
concatenated with autoid
, because the primary key is auto-generated, which results in the column name ProjectBean_autoid
.
The following is a demonstration of the association table for the employee/projects relationship. Employee 1 is assigned to projects a, b, and c. Project a involves employees 1, 2, and 3. The association table contains the following:
EmpBean_empno | ProjectBean_autoid |
---|---|
1 |
a |
1 |
b |
1 |
c |
2 |
a |
3 |
a |
The association table details all relationships between the two entity beans.
To configure the employee/project many-to-many relationship in the deployment description, create an <ejb-relation>
in which each bean defines its <multiplicity>
as many
and defines a <cmr-field>
to the other bean of type Collection
or Set
.
<enterprise-beans> <entity> ... <ejb-name>EmpBean
</ejb-name> <local-home>employee.EmpHome</local-home> <local>employee.Emp</local> ... <cmp-field><field-name>empNo</field-name></cmp-field> <cmp-field><field-name>empName</field-name></cmp-field> <cmp-field><field-name>salary</field-name></cmp-field> <primkey-field>empNo</primkey-field> <prim-key-class>java.lang.Integer</prim-key-class> ... </entity> <entity> ... <ejb-name>ProjectBean
</ejb-name> <local-home>employee.ProjectHome</local-home> <local>employee.Project</local> ... <cmp-field><field-name>projectName</field-name></cmp-field> <prim-key-class>java.lang.Object</prim-key-class> ... </entity> </enterprise-beans> <relationships> <ejb-relation> <ejb-relation-name>Emps-Projects</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Project-has-Emps</ejb-relationship-role-name> <multiplicity>Many
</multiplicity> <relationship-role-source> <ejb-name>ProjectBean
</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>employees
</cmr-field-name> <cmr-field-type>java.util.Collection
</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name>Emp-has-Projects</ejb-relationship-role-name> <multiplicity>Many
</multiplicity> <relationship-role-source> <ejb-name>EmpBean
</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>projects
</cmr-field-name> <cmr-field-type>java.util.Collection
</cmr-field-type> </cmr-field> </ejb-relationship-role> </ejb-relation> </relationships>
The container maps this definition to the following:
empl.jar
and the application name is employee
, then the table names are EmpBean_empl_jar_employee
and ProjectBean_empl_jar_employee
.
<cmp-field>
elements declared in the deployment descriptor.
EmpBean
table are empno
, empname
, and salary
. The primary key is designated as the empno
field.
ProjectBean
table are autoid
for an auto-generated primary key and a projectName
column. The primary key is auto-generated because the <prim-key-class>
is defined as java.lang.Object
, and no <primkey-field>
element is defined.
<cmr-field>
definitions for each of the entity beans in the relationship. The format for the association table name consists of the following, separated by underscores: first bean name, its <cmr-field>
to the second bean, second bean name, its <cmr-field>
to the first bean, JAR file name, and application name. The rule of thirty characters also applies to this table name, as to the entity tables. Thus, the association table name for the employee/projects relationship is ProjectBean_employees_EmpBean_projects_empl_jar_employee. Because this name is over thirty characters, it is truncated to twenty-four characters, and then an underscore plus five characters of a hash code are added. Thus, the official association table would be something like ProjectBean_employees_Em_fj49g
autoid
if auto-generated). In our example, the column names would be EmpBean_empno
and ProjectBean_autoid
. These columns are foreign keys to the entity tables that are involved in the relationship. The EmpBean_empno
foreign key points to the employee table; the ProjectBean_autoid
foreign key points to the projects table.
The following XML demonstrates how to configure a single employee who can have multiple phone numbers. You can add another source of the phone numbers table, such as department phone numbers, so that the department entity bean has a one-to-many relationship with the phone number entity bean. This is why the employee to phone numbers relationship is unidirectional.
The employee entity bean, EmpBean
, defines a <cmr-field>
element designating a Collection
of phoneNumbers
within the PhoneBean
.
<relationships> <ejb-relation> <ejb-relation-name>Emp-Phone</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Emp-PhoneNumbers</ejb-relationship-role-name> <multiplicity>One
</multiplicity> <relationship-role-source> <ejb-name>EmpBean
</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>phoneNumbers
</cmr-field-name> <cmr-field-type>java.util.Collection
</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name>Phone-has-Emp</ejb-relationship-role-name> <multiplicity>Many
</multiplicity> <relationship-role-source> <ejb-name>PhoneBean
</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships>
The container maps this definition to the following:
As "Default Mapping of Relationship Fields to the Database" discusses, your relationship fields can be automatically mapped to the database tables by the container. However, if you do not want to accept the defaults that OC4J provides for you, then you can map the relationships between entity beans within an existing database table and its columns in the orion-ejb-jar.xml
file.
Note: "Explicit Mapping of Persistent Fields to the Database" discusses how to explicitly map persistent fields. This section builds on that information and shows how the relationship mapping occurs. |
For explicit mapping, Oracle recommends that you perform the following steps:
ejb-jar.xml
elements configured.
OC4J creates an orion-ejb-jar.xml
file for you, with the default mappings in it. It is easier to modify these fields than to create them from scratch. This provides you with a method for choosing all or part of the modifications that this discusses.
orion-ejb-jar.xml
file to your development environment.
<entity-deployment>
element in the orion-ejb-jar.xml
file to use the database table and columns you specify.
How you map relationship fields is dependent on the type of relationship:
Modify elements and attributes of the <entity-deployment>
element in the orion-ejb-jar.xml
file to explicitly map relationship fields.
The following XML shows the relevant elements and attributes for explicit mapping of a one-to-one relationship:
<entity-deployment name=" " location=" " table=" " data-source=" "><cmp-field-mapping name=" ">
<entity-ref home=" ">
<cmp-field-mapping name=" " persistence-name=" " />
</entity-ref>
</cmp-field-mapping> </entity-deployment>
The following XML illustrates the relevant elements and attributes for explicitly identifying the association table for one-to-many or many-to-many:
<entity-deployment name=" " location=" " table=" " data-source=" "><cmp-field-mapping name=" ">
<collection-mapping table=" ">
<primkey-mapping>
<cmp-field-mapping name=" " persistence-name=" " />
</primkey-mapping>
<value-mapping type=" ">
<cmp-field-mapping>
<entity-ref home=" ">
<cmp-field-mapping name=" " persistence-name=" "/>
</entity-ref>
</cmp-field-mapping>
</value-mapping>
</collection-mapping>
</cmp-field-mapping>
</entity-deployment>
Figure 4-1 shows a one-to-one unidirectional relationship between an employee and an address. The employee table has a foreign key that points to the primary key of the employee. A one-to-one bidirectional relationship would add a foreign key to the address table that points to the employee.
<enterprise-beans> <entity> ... <ejb-name>EmpBean
</ejb-name> <local-home>employee.EmpHome</local-home> <local>employee.Emp</local> <ejb-class>employee.EmpBean</ejb-class> ... <cmp-field><field-name>empNo</field-name></cmp-field> <cmp-field><field-name>empName</field-name></cmp-field> <cmp-field><field-name>salary</field-name></cmp-field> <primkey-field>empNo</primkey-field> <prim-key-class>java.lang.Integer</prim-key-class> ... </entity> <entity> ... <ejb-name>AddressBean
</ejb-name> <local-home>employee.AddressHome</local-home> <local>employee.Address</local> <ejb-class>employee.AddressBean</ejb-class> ... <cmp-field><field-name>addressPK</field-name></cmp-field> <cmp-field><field-name>addressDescription</field-name></cmp-field> <primkey-field>addressPK</primkey-field> <prim-key-class>java.lang.Integer</prim-key-class> ... </entity> </enterprise-beans> <relationshipe> <ejb-relation> <ejb-relation-name>Emp-Address</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Emp-has-Address </ejb-relationship-role-name><multiplicity>One</multiplicity>
<relationship-role-source><ejb-name>EmpBean
</ejb-name> </relationship-role-source> <cmr-field><cmr-field-name>address</cmr-field-name>
</cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name>Address-has-Emp </ejb-relationship-role-name><multiplicity>One</multiplicity>
<relationship-role-source><ejb-name>AddressBean
</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships
The EmpBean
requires a foreign key to the AddressBean
. Thus, the container modifies the <entity-deployment>
element for the EmpBean
to include a foreign key to the primary key of the AddressBean
. The following mapping for this relationship is located in the orion-ejb-jar.xml
file:
<entity-deployment name="EmpBean" location="emp/EmpBean"wrapper="EmpHome_EntityHomeWrapper2" max-tx-retries="3" table="emp" data-source="jdbc/OracleDS"><primkey-mapping> <cmp-field-mapping name="empNo" persistence-name="empno" /> </primkey-mapping> <cmp-field-mapping name="empName" persistence-name="ename" /> <cmp-field-mapping name="salary" persistence-name="sal" /><cmp-field-mapping name="address">
<entity-ref home="AddressBean">
<cmp-field-mapping name="address"
persistence-name="addressPK" />
</entity-ref>
</cmp-field-mapping>
... </entity-deployment>
This mapping specifies:
<entity-deployment>
attributes define the following:
name
attribute: The name of the source bean is EmpBean
.
location
attribute: The JNDI location is emp/EmpBean
.
table
attribute: The database table in which the persistent data for this entity bean is stored is emp
.
data-source
attribute: The database in which this table resides is defined by the data source jdbc/OracleDS
.
<cmp-field-mapping>
elements identify the table columns and the persistent data to be stored in each: The columns in this table are empno
, ename
, sal
, and address
. The empno
column contains the primary key, as defined in the EmpBean
as empNo
. The empName
and salary
CMP data are saved in the ename
and sal
columns. The address
column is a foreign key that points to the primary key of the AddressBean
table.
address
foreign key points to the primary key of the AddressBean
. The <cmp-field-mapping>
for address
describes this, as follows:
<cmp-field-mapping name="address">
<entity-ref home="AddressBean">
<cmp-field-mapping name="address"
persistence-name="addressPK" />
</entity-ref>
</cmp-field-mapping>
<cmp-field-mapping>
name
attribute identifies the <cmr-field>
that was defined in the source bean. This is the column name for the foreign key called address
in the emp
table. However, it is not mapped to the primary key of the target table here.
<entity-ref>
home
attribute identifies the <ejb-name>
of the target bean. The target in this example is the AddressBean
. The container understands the entity table in which AddressBean
is stored.
<cmp-field-mapping>
name
attribute maps the source foreign key to the primary key of the target table. Thus, this second name
attribute is identical to the first--address
, which is the foreign key of the EmpBean
table. The persistence-name
attribute identifies the primary key column name of the target bean. In this example, the primary key of the AddressBean
table is the addressPK
column.
In the original example, the container auto-generates a primary key for the target AddressBean
table. For the auto-generated example, the second <cmp-field>
mapping is mapped to an auto-generated primary key, known as autoid
, as follows:
<cmp-field-mapping name="address" persistence-name="autoid" />
Figure 4-4 displays the relationship mapping of the EmpBean
address
foreign key to the AddressBean
addressPK
primary key.
In summary, an address
column in the EmpBean_empl_jar_employee
table is a foreign key that points to the primary key, addressPK
, in the AddressBean_empl_jar_employee
table. For the example in which the AddressBean
has an auto-generated primary key, an address
column in the EmpBean_empl_jar_employee
table is a foreign key that points to the primary key, autoid
, in the AddressBean_empl_jar_employee
table.
Figure 4-3 shows a one-to-many unidirectional relationship between an employee and his/her phone numbers. Because this involves a "many" in the relationship, an association table is created. The association table is the same whether this is a unidirectional or bidirectional, or one-to-many or many-to-many relationship.
In the ejb-jar.xml
file, the cardinality is defined in the <relationships>
element. The container knows from this definition whether the relationship is one-to-many or many-to-many. In the orion-ejb-jar.xml
file, the mapping of this relationship to an association table is described in a <collection-mapping>
element. Because the cardinality is already known, only one entity in the relationship defines the <collection-mapping>
element.
<collection-mapping>
element as it receives back a Collection
or Set
of the target.
<collection-mapping>
element with the association table specifications. The other entity bean has an empty <collection-mapping>
element.
In the orion-ejb-jar.xml
file for the employee example, the EmpBean
<entity-deployment>
element defines the <collection-mapping>
element to designate a Collection
of phone numbers. The <collection-mapping>
element defines the association table.
<entity-deployment name="EmpBean" location="emp/EmpBean"
wrapper="EmpHome_EntityHomeWrapper2" max-tx-retries="3" table="EmpBean_phoneNumbers_Pho8fj49g" data-source="jdbc/OracleDS">
<primkey-mapping>
<cmp-field-mapping name="empNo" persistence-name="empno" />
</primkey-mapping>
<cmp-field-mapping name="empName" persistence-name="ename" /> <cmp-field-mapping name="salary" persistence-name="sal" /><cmp-field-mapping name="phoneNumbers">
<collection-mapping table="EmpBean_phoneNumbers_Pho8fj49g">
<primkey-mapping>
<cmp-field-mapping name="empNo" persistence-name="EmpBean_empno" />
</primkey-mapping>
<value-mapping type="employee.PhoneLocal">
<cmp-field-mapping>
<entity-ref home="PhoneBean">
<cmp-field-mapping name="phoneNumbers"
persistence-name="PhoneBean_autoid"/>
</entity-ref>
</cmp-field-mapping>
</value-mapping>
</collection-mapping>
</cmp-field-mapping>
... </entity-deployment>
<collection-mapping>
element is contained within the <cmp-field-mapping>
for phoneNumbers
, which is the EmpBean
<cmr-field>
element definition. It defines the association table name in the table
attribute, which currently defines the association table name as EmpBean_phoneNumbers_Pho8fj49g
.
<primkey-mapping>
and <value-mapping>
elements respectively.
EmpBean_empno
and PhoneBean_autoid
.
<value-mapping>
element specifies the target entity bean.
You can bypass an association table in the one-to-many bidirectional entity relationship. The "one" relationship has a primary key that points to the "many"; the "many" has a foreign key that points back. With both tables maintaining primary keys, and the "many" table maintaining a foreign key back to the "one" table, there is no need for an association table.
Figure 4-6 shows the department<->employee example, where each employee belongs to only one department and each department can contain multiple employees. The department table has a primary key. The employee table has a primary key to identify each employee and a foreign key to point back to the employee's department. If you want to find the department for a single employee, a simple SQL statement retrieves the department information from the foreign key. To find all employees in a department, the container performs a JOIN statement on both the department and employee tables and retrieves all employees with the designated department number.
This is not the default behavior. To have this type of relationship, do one of the following:
-DassociateUsingThirdTable=false
on the OC4J.JAR startup options before deployment. Restart the OC4J instance.
<collection-mapping>
element in the orion-ejb-jar.xml
file.
To manipulate the <collection-mapping>
element in the orion-ejb-jar.xml
file, you modify the <entity-deployment>
element for the "one" entity bean, which contains the Collection
, as follows:
<collection-mapping>
table
attribute to be the "many" table. In this example, you would modify this attribute to be the EmpBean_empl_jar_employee
table.
persistence-name
attribute for each entity bean in the <collection-mapping>
table as follows:
persistence-name
of the <primkey-field>
element should be the primary key of the source entity bean and the database column name of the foreign key in the target entity bean.
<value-mapping>
element provides a pointer to the target bean--the "many" bean. Thus, the <entity-ref>
home
attribute should be the target entity bean name. In the second <cmp-field-mapping>
element, the name
attribute contains the <cmr-field>
defined in the "one" entity bean in the orion-ejb-jar.xml
file. The persistence-name
attribute defines the primary key column of the "one" entity bean table.
Figure 4-7 demonstrates how the department/employee one-to-many bidirectional example is mapped without the use of an association table.
|
Copyright © 2002 Oracle Corporation. All Rights Reserved. |
|