Oracle® Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide
10g Release 2 (10.1.2) Part No. B15505-01 |
|
![]() Previous |
![]() Next |
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:
Accept the defaults for these fields and avoid more deployment descriptor configuration. See "Default Mapping of Relationship Fields to the Database" to learn how the default mapping occurs. The tables are automatically created for the bean based on the information in the ejb-jar.xml
file.
Map the fields to columns in a table that already exists in a designated database. The persistent data mapping is configured within the 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 5, "CMP Entity Beans" discusses persistent field mapping. |
When you declare relationship fields in the ejb-jar.xml
file, OC4J provides default mappings of these fields to the database when it auto-generates the orion-ejb-jar.xml
file. The default mapping for relationships is the same as for the persistent fields, as described in "Default Mapping of Persistent Fields to the Database".
Note: For all future redeployments, copy the auto-generatedorion-ejb-jar.xml file with this table name into the same directory as your ejb-jar.xml file from the J2EE_HOME/application-deployments directory. Thus, all future redeployments have the same table names as first generated. If you do not copy this file over, different table names may be generated.
|
In summary, these defaults include:
Database—The default database as set up in your OC4J instance configuration.
Default table—Each entity bean in the relationship represents data in its own database table. The name of the entity bean table makes an effort to be unique, and so it is constructed with the following names, where each is separated by an underscore (_):
EJB name defined in <ejb-name>
in the deployment descriptor.
JAR file name, including the .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.
Application name: You define the application name during deployment.
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
.
Column names in each table—The container generates columns in each table based on the <cmp-field>
and <cmr-field>
elements defined in the deployment descriptor. A column is created for each <cmp-field>
element that relates to the entity bean data. In addition, a column is created for each <cmr-field>
element that represents a relationship. In a unidirectional relationship, only a single entity in the relationship defines a <cmr-field>
in the deployment descriptor. In 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:
In the default one-to-one relationship, the foreign key is created in the database table for the source EJB and is directed to the primary key of the target database table. For example, if one employee has one address, then the foreign key is created within the employee table that points to the primary key of the address table. For more information, see "Example of a Default Mapping of the One-To-One Relationship".
The default for one-to-many relationships uses a foreign key as described in "Using a Foreign Key with the One-To-Many Relationship".
The default for many-to-many relationships creates an association table (a third table). The association table contains two foreign keys, where each points to the primary key of one of the entity tables. For more information, see "Example of a Default Mapping of One-To-Many and Many-To-Many Relationships".
Since the <cmp-field>
and <cmr-field>
elements represent Java data types, they may not convert to database types in the manner you believe that they should. See "Conversion of CMP Types to Database Types" for a table of how the conversion occurs. However, you can modify the translation rules for converting Java data types to database data types in the specific database XML files, which are located in j2ee/home/config/database-schemas
. This directory includes all database files. The Oracle database conversion file is named oracle.xml
.
Primary key generation—Both entity tables contain a primary key. The primary key can be defined or auto-generated. See "How to Define and Use Primary Keys for Your Entity Bean" for a full description.
Defined primary key: The primary key is generated as designated in the <primkey-field>
element as a simple data type or a class. Thus, the column name is the same as the name in the <primkey-field>
element.
Composite primary key: The primary key is defined within a class, and is made up of several fields. Each field within the composite primary key is represented by a column in the database table, where each is considered part of the primary key in the table.
Auto-generated primary key: If you specify a 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 column is named AUTOID.
The one-to-one entity relationship is managed between the entity tables with a foreign key. Figure 6-1 demonstrates the default table mapping of a one-to-one unidirectional relationship between the employee and address bean.
The container generates the table names based on the entity bean names, the JAR file the beans are archived in, and the application name that they are deployed under. If the JAR filename is empl.jar
and the application name is employee
, then the table names are EmpBean_empl_jar_employee
and AddressBean_empl_jar_employee
.
The container generates columns in each table based on the <cmp-field>
and <cmr-field>
elements declared in the deployment descriptor.
The columns for the 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.
The columns for the AddressBean
table are an auto-generated long primary key and columns for street, city, state, and zip.
The primary key for the employee table is designated in the deployment descriptor as empno
. The AddressBean
is configured for an auto-generated primary key by specifying only <primkey-class>
of java.lang.Object
.
As described in "One-To-Many or Many-To-One Relationship Overview", one bean, such as a department, can have a relationship to multiple instances of another bean, such as employees. There are several employees in each department. Since this is a bidirectional relationship, you can look up the department from the employee. The relationships between the DeptBean
and EmpBean
is represented by CMR fields, employees
and dept
, as shown in Figure 6-2.
How this relationship is mapped to database tables depends on your choices. The default method adds a foreign key to the table that defines the "many" side of the relationship—in this case, the table that represents the EmpBean
. The foreign key points back to the department to which each employee belongs.
Figure 6-3 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.
Figure 6-3 Default Mapping for One-To-Many Bean Relationship Example
"Using a Foreign Key with the One-To-Many Relationship" details how the deployment descriptors are configured for this behavior to occur. To keep the same defaults for all future redeployments, copy the auto-generated orion-ejb-jar.xml
file with the default table name into the same directory as your ejb-jar.xml
file from the J2EE_HOME/application-deployments
directory. Thus, all future redeployments have the same table names as first generated. If you do not copy this file over, different table names may be generated. To modify the defaults, copy the file over and follow the directions in "Using a Foreign Key with the One-To-Many Relationship".
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 or if you need to map the fields to an existing database table, then you can map the relationships between entity beans to an existing database table and its columns in the orion-ejb-jar.xml
file.
"Explicit Mapping of Persistent Fields to the Database" discusses how to explicitly map CMP fields. This section is about mapping CMR fields and so builds on that information to show how the relationship mapping occurs.
Important: You modify elements and attributes of the<entity-deployment> element in the orion-ejb-jar.xml file to explicitly map relationship fields. JDeveloper was created to manage the complex mapping between the entity beans and the database tables. Thus, JDeveloper validates the deployment descriptors and prevents inconsistencies. You are allowed to modify the orion-ejb-jar.xml file on your own; however, we suggest that you use JDeveloper for modifying container-managed relationships. CMR configuration is complex and can be difficult to understand. You can download JDeveloper at the following site: http://www.oracle.com/technology/software/products/jdev/index.html
|
This chapter provides two levels of information about the orion-ejb-jar.xml
elements:
A quick, direct guide for identifying the fields in which you would modify if you mapped to an existing database. See "Quick Cookbook for Matching an Existing Database to the Bean Mappings".
An education on all elements used in the CMR mapping and directions on modifying them. See "Steps for Modifying CMR Mapping Elements".
If you want to know how to modify the orion-ejb-jar.xml
file without understanding what each of the elements are for in this XML file and you do not want to use JDeveloper, then do the following:
Deploy your bean with the autocreate-tables
element set to false in the orion-application.xml
file.
Copy the orion-ejb-jar.xml
file from the application-deployments/
directory to your development directory.
Modify the data-source
element to be the correct data source. Note that all beans that are associated with each other must use the same data source.
Modify the table
attribute to be the correct table. Make sure that it is the correct table for the bean that is defined in the <entity-deployments>
element.
Modify the persistence-name
attributes to the correct column for each bean persistence type, whether a CMP or CMR field.
Set the autocreate-tables
element in orion-application.xml
file to true.
Rearchive your application and redeploy.
Note: An object-relationship entity bean example is available on OTN from the OC4J sample code page athttp://www.oracle.com/technology/tech/java/oc4j/demos/ on the OTN Web site.
|
If JDeveloper does not provide the mapping that you need or if you wish to manage the XML on your own, then you should perform the following steps:
Deploy your bean with the autocreate-tables
element set to false in the orion-application.xml
file and the 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.
Copy the container-created orion-ejb-jar.xml
file from the $J2EE_HOME
/application-deployments
directory to your development environment.
Modify the <entity-deployment>
element in the orion-ejb-jar.xml
file to use the database table and columns you specify, based on the relationship type. See "Hand-Editing the orion-ejb-jar.xml File to Map Bean Relationships to Database Tables" for an overview.
Each of the following sections describes how the CMR mapping occurs for each relationship type:
Set the autocreate-tables
element in orion-application.xml
file to true.
Rearchive your application and redeploy.
The relationship between the beans is defined in the <relationships>
element in the ejb-jar.xml
file; the mapping between the bean and the database table and columns is specified in the <entity-deployment>
element in the orion-ejb-jar.xml
file.
The orion-ejb-jar.xml
file maps the bean entity relationships to database table and columns within a <cmp-field-mapping>
element. The following is the XML structure of the <entity-deployment>
and <cmp-field-mapping>
elements for a simple one-to-one relationship:
<entity-deployment name="SourceBeanName" location="JNDIlocation"
table="TableName" data-source="DataSourceJNDIName">
...
<cmp-field-mapping name="
CMRfield_name">
<entity-ref home="
targetBeanName">
<cmp-field-mapping name="
CMRfield_name" persistence-name="
targetBean_PKcolumn" />
</entity-ref>
</cmp-field-mapping>
Within this element, you can define the bean name (the source of the relationship that indicates the direction), the JNDI location, the database table to which the information is persisted, and map each of the CMP and CMR fields defined in the ejb-jar.xml
file to the underlying persistence storage—the database.
Note: This document refers to beans as the source or target of a relationship. If an employee owns many phones in a unidirectional relationship, then the employee is the source bean and it points to the phones, which are the target. |
The attributes of the <entity-deployment>
element define the following for the bean:
The name
attribute identifies the EJB name of the bean, which was defined in the <ejb-name>
element in the ejb-jar.xml
file. This name
attribute connects the ejb-jar.xml
file definition for the bean to its mapping to the database.
The location
attribute identities the JNDI name of the bean.
The table
attribute identifies the database table to which this entity bean is mapped.
The data-source
attribute identifies the database in which the table resides. The data source must be the same for all beans that interact with each other or are associated with each other. This includes beans that are in the same application, part of the same transaction, or beans that are in a parent-child relationship.
The <cmp-field-mapping>
element in the orion-ejb-jar.xml
file maps the following fields to database columns.
The <cmp-field>
element in the ejb-jar.xml
file defines a CMP field.
The <cmr-field>
element in the ejb-jar.xml
file defines a CMR field.
Figure 6-4 displays how the <cmr-field>
element in the ejb-jar.xml
file maps to the <cmp-field-mapping>
element in the orion-ejb-jar.xml
file. The name
attribute in the <cmp-field-mapping>
provides the link between the two XML files. You must not modify any name
attributes.
Figure 6-4 Demonstration of Mapping for a One-To-One Relationship
To fully identify and map CMR fields, nested <cmp-field-mapping>
elements are used. The format of the nesting depends on the type of relationship. The database column that is the primary key of the target bean is defined in the persistence-name
attribute of the internal <cmp-field-mapping>
element. If you have an existing database, you would be modifying the persistence-name
attributes for each <cmp-field-mapping>
element to match your column names.
The following sections talk about each relationship type and how the mapping occurs:
Figure 6-5 demonstrates a one-to-one unidirectional relationship between a single employee and his/her address. The EmpBean
points to the AddressBean
that is the employee's address using the CMR field, address
.
Figure 6-6 shows the database tables, EMP
and ADDRESS
, to which these beans will map. The EMP
table has a foreign key, named address
, which points to the primary key of the ADDRESS
table, AddressPK
.
The beans and their relationships are specified in both of the deployment descriptors. As Figure 6-7 shows, in the ejb-jar.xml
file, the one-to-one relationship between the EmpBean
and AddressBean
is defined within a <relationships>
element. The direction is designated by one or two <cmr-field>
elements.
The mapping of the beans to their database persistent storage is defined in the orion-ejb-jar.xml
file. The one-to-one relationship—whether bidirectional or unidirectional—is mapped on both sides with an <entity-ref>
element inside a <cmp-field-mapping>
element. The <entity-ref>
describes the target entity bean of the relationship.
Figure 6-7 Demonstration of Mapping for a One-To-One Relationship
To map your bean fields to an existing database, you need to understand the fields within the <cmp-field-mapping>
element in the orion-ejb-jar.xml
file. This element has the following structure:
<cmp-field-mapping name="
CMRfield_name">
<entity-ref home="
targetBeanName">
<cmp-field-mapping name="
CMRfield_name" persistence-name="
targetBean_PKcolumn" />
</entity-ref>
</cmp-field-mapping>
The name
attribute of the <cmp-field-mapping>
element is the same as the <cmp-field>
element in the ejb-jar.xml
file. Do not modify the name
attribute in the <cmp-field-mapping>
element.
The target bean name is specified in the home
attribute of the <entity-ref>
element.
The database column that is the primary key of the target bean is defined in the persistence-name
attribute of the internal <cmp-field-mapping>
element. If you have an existing database, modify the persistence-name
attributes for each <cmp-field-mapping>
element to match your column names.
Example 6-5 The XML Configuration for One-to-One Unidirectional
The ejb-jar.xml
file configuration defines a one-to-one unidirectional relationship between the EmpBean
and AddressBean
.
<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> <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>
The EmpBean
defines a <cmr-field>
for the direction of the relationship showing that each employee has one address. The EMP
table that supports EmpBean
requires a foreign key to point to the table that supports the AddressBean
.
The foreign key from the EMP
table to the ADDRESS
table is identified as address
within the <cmr-field-name>
element, which is required on the name
attribute of the <cmp-field-mapping>
element in the orion-ejb-jar.xml
file. Thus, address
is the identifier that links the relationship defined in the ejb-jar.xml
file to the persistence storage mapping specified in the orion-ejb-jar.xml
file.
The following is the orion-ejb-jar.xml
file with the elements modified to map to the existing database tables:
<entity-deployment name="EmpBean" location="emp/EmpBean" ...
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>
<entity-deployment name="AddressBean" location="emp/AddressBean" ... table="ADDRESS" data-source="jdbc/OracleDS"... >
<primkey-mapping>
<cmp-field-mapping name="addressPK" persistence-name="addressPK" />
</primkey-mapping>
<cmp-field-mapping name="street" persistence-name="street" />
<cmp-field-mapping name="city" persistence-name="city" />
<cmp-field-mapping name="state" persistence-name="state" />
<cmp-field-mapping name="zip" persistence-name="zip" />
<cmp-field-mapping name="EmpBean_address">
<entity-ref home="EmpBean">
<cmp-field-mapping name="EmpBean_address" persistence-name="EMPNO" />
</entity-ref>
</cmp-field-mapping>
...
</entity-deployment>
Note: This section describes in detail how logical names defined in theejb-jar.xml file relate to those in the orion-ejb-jar.xml file. And it describes how the logical variables defined in the orion-ejb-jar.xml file relate to the database table and column names. This chapter specifically chooses different names for closely aligned elements in the ejb-jar.xml and orion-ejb-jar.xml files in order that you can understand which names where the mappings occur. However, for efficiency and ease, you can make all related names the same. For example, instead of identifying address and addressPK for identifying the CMR field name and database column name, you could use one name, address , for all of them. Your configuration is easier if all these names are the same.
|
The <entity-deployment>
mapping for the EmpBean
specifies:
The <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
.
The <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 in the EmpBean
table, EMP
, that points to the primary key of the AddressBean
table.
The <cmp-field-mapping>
element for the foreign key defines the following:
Both of the name
attributes identify the <cmr-field>
that was defined in the ejb-jar.xml
file. This name is address
.
The <entity-ref>
home
attribute identifies the <ejb-name>
of the target bean. The target in this example is the AddressBean
.
The persistence-name
attribute identifies the primary key column name of the target bean. In this example, the primary key of the AddressBean
table, ADDRESS
, is the addressPK
column.
Figure 6-8 displays the relationship mapping of the EmpBean
address
foreign key to the AddressBean
addressPK
primary key.
Figure 6-8 Demonstration of Explicit Mapping for a One-To-One Relationship
In summary, an address
column in the EMP
table is a foreign key that points to the primary key, addressPK
, in the ADDRESS
table. For the example in which the AddressBean
has an auto-generated primary key, an address
column in the EMP
table is a foreign key that points to the primary key, autoid
, in the ADDRESS
table.
As described in "Defining an Auto-Generated Primary Key for Your Entity Bean", you can define that a table use an automatic identifier as the primary key. This results in the following XML configuration in the orion-ejb-jar.xml
file for the bean:
<primkey-mapping> <cmp-field-mapping name="auto_id" persistence-name="autoid"/> </primkey-mapping>
In our employee/address example, if the AddressBean
had a primary key undefined, so that it defaulted to an autoid
, then the table mapping would be as follows:
Figure 6-9 One-To-One Employee Relationship Example with Auto-ID
As described in "One-To-Many or Many-To-One Relationship Overview", one bean, such as a department, can have a relationship to multiple instances of another bean, such as employees. There are several employees in each department. Since this is a bidirectional relationship, you can look up the department from the employee. The relationships between the DeptBean
and EmpBean
is represented by CMR fields, employees
and deptno
, as shown in Figure 6-10.
How this relationship is mapped to database tables depends on your choices. The default method is add a foreign key to the table that defines the "many" side of the relationship—in this case, the table that represents the EmpBean
. The foreign key points back to the department to which each employee belongs.
Figure 6-11 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.
Figure 6-11 Explicit Mapping for One-To-Many Bidirectional Relationship Example
This is the default behavior. If you need to change the mappings to other database tables, then you use either JDeveloper or hand-edit the orion-ejb-jar.xml
file to manipulate the <collection-mapping>
or <set-mapping>
element.
Important: You modify elements and attributes of the<entity-deployment> element in the orion-ejb-jar.xml file to explicitly map relationship fields. JDeveloper was created to manage the complex mapping between the entity beans and the database tables. Thus, JDeveloper validates the deployment descriptors and prevents inconsistencies. You are allowed to modify the orion-ejb-jar.xml file on your own; however, we suggest that you use JDeveloper for modifying container-managed relationships. CMR configuration is complex and can be difficult to understand. You can download JDeveloper at the following site: http://www.oracle.com/technology/software/products/jdev/index.html
|
Example 6-6 shows the table mapping for the bidirectional relationship of one department with many employees. The "one" side of the relationship is the department; the "many" side of the relationship is the employee. Figure 6-11 shows the table design. This demonstrates how to hand-edit the orion-ejb-jar.xml
file for this relationship to use a foreign key.
Example 6-6 One-To-Many Relationship Using a Foreign Key
The ejb-jar.xml
<relationships>
section defines the department-employee bidirectional example, as follows:
<relationships> <ejb-relation> <ejb-relation-name>Dept-Emps</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Dept-has-Emps </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>DeptBean</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>employees</cmr-field-name> <cmr-field-type>java.util.Set</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name>Emps-have-Dept </ejb-relationship-role-name> <multiplicity>Many</multiplicity> <cascade-delete/> <relationship-role-source> <ejb-name>EmpBean</ejb-name> </relationship-role-source> <cmr-field><cmr-field-name>dept</cmr-field-name></cmr-field> </ejb-relationship-role> </ejb-relation> </relationships>
The orion-ejb-jar.xml
file maps this definition in the following XML. If the table identified in the <collection-mapping>
or <set-mapping>
element of the "one" relationship (the department) is the name of the target bean's table (the employee bean table), then the one-to-many relationship is defined with a foreign key. For example, the table
attribute in the department definition is EMP
.
<?xml version = '1.0' encoding = 'windows-1252'?> <!DOCTYPE orion-ejb-jar PUBLIC "-//Evermind//DTD Enterprise JavaBeans 2.0 runtime//EN" " http://xmlns.oracle.com/ias/dtds/orion-ejb-jar.dtd"> <orion-ejb-jar> <enterprise-beans> <entity-deployment name="DeptBean" data-source="jdbc/scottDS" table="DEPT"> <primkey-mapping> <cmp-field-mapping name="deptno" persistence-name="DEPTNO" /> /*PK*/ </primkey-mapping> <cmp-field-mapping name="dname" persistence-name="DNAME" /> <cmp-field-mapping name="employees">/*points from DEPTNO column in EMP to DEPTNO in DEPT*/ 1. <collection-mapping table="EMP"> /*table where FK lives*/ <primkey-mapping>
<cmp-field-mapping name="DeptBean_deptno"> /*CMR field name*/ <entity-ref home="DeptBean"> /*points to DeptBean*/ 2. <cmp-field-mapping name="DeptBean_deptno" persistence-name="EDEPTNO"/> </entity-ref> </cmp-field-mapping> </primkey-mapping> <value-mapping type="mypackage1.EmpLocal">
<cmp-field-mapping name="EmpBean_empno"> <entity-ref home="EmpBean">
<cmp-field-mapping name="EmpBean_empno" persistence-name="EMPNO"/> </entity-ref> </cmp-field-mapping> </value-mapping> </collection-mapping> </cmp-field-mapping> </entity-deployment> <entity-deployment name="EmpBean" data-source="jdbc/scottDS" table="EMP"> <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="dept"> /*foreign key*/ <entity-ref home="DeptBean"> 2. <cmp-field-mapping name="dept" persistence-name="EDEPTNO" /> </entity-ref> </cmp-field-mapping> </entity-deployment> </enterprise-beans> <assembly-descriptor> <default-method-access> <security-role-mapping impliesAll="true" name="<default-ejb-caller-role>"/> </default-method-access> </assembly-descriptor> </orion-ejb-jar>
The foreign key is defined in the database table of the "many" relationship. In our example, the EDEPTNO
foreign key column exists in the EMP
database table. This is defined in a persistence-name
attribute of the <cmp-field-mapping>
element in the EmpBean
configuration.
Thus, to manipulate the <collection-mapping>
or <set-mapping>
element in the orion-ejb-jar.xml
file, modify the <entity-deployment>
element for the "one" entity bean, which contains the Collection
, as follows:
Modify the table in the <collection-mapping>
or <set-mapping>
table
attribute in the "one" relationship to be the database table of the "many" relationship. In this example, you would modify this attribute to be the EMP
table.
Modify the foreign key that points to the "one" relationship within the "many" relationship configuration. In this example, modify the <cmp-field-mapping>
element to specify the EDEPTNO
foreign key in the persistence-name
attribute.
These steps are delineated in the code example in Example 6-6.
An example of a unidirectional one-to-many relationship is the employee/phones example. An employee can own one or more phone numbers; however, you cannot look up an employee given a phone number. Figure 6-12 demonstrates the bean relationship.
Figure 6-13 shows the employee—>phone numbers example, where each employee can have multiple phone numbers. The employee table has a primary key. The phone numbers table has a auto-id for the primary key, the phone number, and a foreign key to point back to the employee. If you want to find all phone numbers for a single employee, the container performs a JOIN statement on both the employee and phone number tables and retrieves all phone numbers with the designated employee number.
Figure 6-13 Explicit Mapping for One-to-Many Bean Relationship Example
Example 6-7 One-to-Many Unidirectional Example With Foreign Key
The ejb-jar.xml
<relationships>
section defines the employee-phone numbers unidirectional example, as follows:
<entity> <ejb-name>EmpBean</ejb-name> ... <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>PhoneBean</ejb-name> ... <cmp-field><field-name>phoneNo</field-name></cmp-field> <prim-key-class>java.lang.Object</prim-key-class> </entity> <relationships> <ejb-relation> <ejb-relation-name>Emp-Phone</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Emp-has-Phones </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>EmpBean</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>phones</cmr-field-name> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name>Phones-have-Emp </ejb-relationship-role-name> <multiplicity>Many</multiplicity> <cascade-delete/> <relationship-role-source> <ejb-name>PhoneBean</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships>
The orion-ejb-jar.xml
file maps this definition in the following XML. If the table identified in the <collection-mapping>
or <set-mapping>
element of the "one" relationship (the employee) is the name of the target bean's table (the phone bean table), then the container defines the one-to-many relationship with a foreign key. In this example, the target bean's table is the PHONE
database table.
<entity-deployment name="EmpBean" table="EMP"> <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="phones"> 1. <collection-mapping table="PHONE"> <primkey-mapping> <cmp-field-mapping name="EmpBean_empno"> <entity-ref home="EmpBean"> 2. <cmp-field-mapping name="EmpBean_empNo" persistence-name="EMPNO"/> </entity-ref> </cmp-field-mapping> </primkey-mapping> <value-mapping type="hr.PhoneLocal"> <cmp-field-mapping name="autoid"> <entity-ref home="PhoneBean"> <cmp-field-mapping name="autoid" persistence-name="AUTOID"/> </entity-ref> </cmp-field-mapping> </value-mapping> </collection-mapping> </cmp-field-mapping> </entity-deployment> <entity-deployment name="PhoneBean" table="PHONE"> <primkey-mapping> <cmp-field-mapping name="autoid" persistence-name="AUTOID"/> </primkey-mapping> <cmp-field-mapping name="phoneNo" persistence-name="PHONE_NO" /> <cmp-field-mapping name="EmpBean_phones"> <entity-ref home="EmpBean"> 2. <cmp-field-mapping name="EmpBean_phones" persistence-name="EMPNO" /> </entity-ref> </cmp-field-mapping> </entity-deployment>
The foreign key is defined in the database table of the "many" relationship. In our example, the EMPNO
foreign key column exists in the PHONE
database table. This is defined in a persistence-name
attribute of the <cmp-field-mapping>
element in the PhoneBean
configuration.
Thus, to manipulate the <collection-mapping>
or <set-mapping>
element in the orion-ejb-jar.xml
file, modify the <entity-deployment>
element for the "one" entity bean, which contains the Collection
, as follows:
Modify the table in the <collection-mapping>
or <set-mapping>
table
attribute in the "one" relationship to be the database table for the "many" relationship. In this example, you would modify this attribute to be the PHONE
table.
Modify the foreign key that points to the "one" relationship within the "many" relationship configuration. In this example, modify the <cmp-field-mapping>
element to specify the EMPNO
foreign key in the persistence-name
attribute.
These steps are delineated in the code example in Example 6-7.
As described in "One-To-Many or Many-To-One Relationship Overview", one bean, such as a department, can have a relationship to multiple instances of another bean, such as employees. There are several employees in each department. Since this is a bidirectional relationship, you can look up the department from the employee. The relationships between the DeptBean
and EmpBean
is represented by CMR fields, employees
and deptno
, as shown in Figure 6-14.
How this relationship is mapped to database tables depends on your choices. You could choose to use a separate table, known as an association table, which maps the two tables together appropriately with two foreign keys, where each foreign key points to each of the entity tables in the relationship.
Note: If you have a composite primary key in either or both tables, the foreign key will be a composite foreign key; thus, the association table will have the appropriate number of columns for each part of the composite foreign key. |
This is not the default behavior. To have this type of relationship, do one or both of the following:
Specify -DassociateUsingThirdTable=true
on the OC4J startup options before deployment. Restart the OC4J instance. This generates the association table for all applications deployed after the restart.
You can modify the mappings either through JDeveloper or by hand-editing the orion-ejb-jar.xml
file.
Important: You modify elements and attributes of the<entity-deployment> element in the orion-ejb-jar.xml file to explicitly map relationship fields. JDeveloper was created to manage the complex mapping between the entity beans and the database tables. Thus, JDeveloper validates the deployment descriptors and prevents inconsistencies. You are allowed to modify the orion-ejb-jar.xml file on your own; however, we suggest that you use JDeveloper for modifying container-managed relationships. CMR configuration is complex and can be difficult to understand. You can download JDeveloper at the following site: http://www.oracle.com/technology/software/products/jdev/index.html
|
Figure 6-15 shows the tables that are created for the employee/project relationship.
Figure 6-15 Many-to-Many Employee Bean Relationship Example
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 for this example contains two foreign key columns: one that points to the employee table and one that points to the project table. The column names of the association table are a concatenation of the entity bean name in <ejb-name>
element of the ejb-jar.xml
file 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 following are the names for the foreign keys of our employee/project 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.
Example 6-8 Deployment Descriptor for a Many-To-Many Relationship
The deployment descriptors for the employee/project many-to-many relationship contains an <ejb-relation>
element 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:
The container generates the entity tables based on the entity bean names, the JAR file that the beans are archived in, and the application name that they are deployed under. If the JAR filename is empl.jar
and the application name is employee
, then the table names are EmpBean_empl_jar_employee
and ProjectBean_empl_jar_employee
.
The container generates columns in each entity table based on the <cmp-field>
elements declared in the deployment descriptor.
The columns for the EmpBean
table are empno
, empname
, and salary
. The primary key is designated as the empno
field.
The columns for the 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.
The container generates an association table in the same manner as the entity table.
The association table name is created to include the two <cmr-field>
element 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
Two foreign keys in the association table are created. In this example, each foreign key is defined in a column, where the name is a concatenation of the bean name and the primary key (or 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.
Example 6-9 Deployment Descriptor for One-To-Many Unidirectional Relationship
Figure 6-16 shows the default database tables for the employee/phone numbers example.
Figure 6-16 One-To-Many Employee Bean Relationship Example
Each employee can have multiple phone numbers. The employee entity bean, EmpBean
, defines a <cmr-field>
element designating a Collection
of phoneNumbers
within the PhoneBean
. The deployment descriptors for this exmple are as follows:
<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>
Note: An object-relationship entity bean example is available on OTN from the OC4J sample code page athttp://www.oracle.com/technology/tech/java/oc4j/demos/ on the OTN Web site.
|
The relationship that is defined in the ejb-jar.xml
file is mapped in the orion-ejb-jar.xml
file within a <cmp-field-mapping>
element. The <cmp-field-mapping>
element contains either a <collection-mapping>
or <set-mapping>
element. Our example contains a department has many employees. The department describes its "many" relationship to employees with a <collection-mapping>
element.
Note: The "many" side of the relationship is defined by the<collection-mapping> or <set-mapping> element. The "one" side of the relationship is defined by the <entity-ref> element. Thus, for a one-to-many relationship, a single <collection-mapping> element is used to describe the "many" side.
|
The XML structure for defining a one-to-many relationship includes the following:
<cmp-field-mapping name="
CMRfield">
<collection-mapping table="
association_table">
<primkey-mapping>
<cmp-field-mapping name="
CMRfield" persistence-name="
first_column_name_assoc_table" />
</primkey-mapping>
<value-mapping type="
target_bean_local_home_interface">
<cmp-field-mapping>
<entity-ref home="
target_bean_EJBname">
<cmp-field-mapping name="
CMRfield" persistence-name="
second_column_name_assoc_table"/>
</entity-ref>
</cmp-field-mapping>
</value-mapping>
</collection-mapping>
</cmp-field-mapping>
Element or Attribute | Description |
---|---|
<cmp-field-mapping>
|
This element maps a persistent field or a relationship field. For relationship fields, it will contain either an <entity-ref> for a one-to-one mapping or a <collection-mapping> for a one-to-many, many-to-one, or many-to-many relationship.
|
<entity-ref>
|
This element identifies the target bean and its primary key to which the foreign key points.
|
<collection-mapping>
|
This element explicitly maps the "many" side of a relationship.
This element defines two elements, one for each column in the association table:
|
<primkey-mapping>
|
Within the <collection-mapping> , use this element to identify the first foreign key. You can modify the persistence-name attribute in this element to match the column name in your own association table.
|
<value-mapping>
|
Use this element to specify the second foreign key. The type attribute identifies the local interface for the target bean. You can modify the persistence-name attribute in this element to match the column name in your own association table.
|
The following example shows how a one-to-many bidirectional relationship is configured to use an association table. In the ejb-jar.xml
file, the department defines itself as the "one" side of the relationship and shows that it expects to receive back "many" employees through the definition of a Collection
in the <cmr-field>
element. The employee defines itself as the "many" side of the relationship.
<relationships>
<ejb-relation>
<ejb-relation-name>Dept-Emps</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>Dept-has-Emps </ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source> <ejb-name>DeptBean</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-Dept </ejb-relationship-role-name>
<multiplicity>Many</multiplicity>
<relationship-role-source> <ejb-name>EmpBean</ejb-name> </relationship-role-source>
<cmr-field>
<cmr-field-name>dept</cmr-field-name> </cmr-field>
</ejb-relationship-role>
</ejb-relation>
</relationships>
In the orion-ejb-jar.xml
file, the mapping of this relationship to an association table is described in a <collection-mapping>
element. Since this is a one-to-many relationship, the "one" entity bean, the department, has the <collection-mapping>
element as it receives back a Collection
or Set
of the target, the employees.
In the orion-ejb-jar.xml
file, the DeptBean
<entity-deployment>
element defines the <collection-mapping>
element to designate a Collection
of employees. The <collection-mapping>
element defines the association table.
<entity-deployment name="
DeptBean" location="DeptBean"
table="DEPT" data-source="jdbc/OracleDS" ... >
<primkey-mapping>
<cmp-field-mapping name="deptNo" persistence-name="deptNo" />
</primkey-mapping>
<cmp-field-mapping name="deptName" persistence-name="deptName" />
<cmp-field-mapping name="
employees">
<collection-mapping table="DEPT_EMP"><primkey-mapping>
<cmp-field-mapping name="DeptBean_deptno">
<entity-ref home="DeptBean">
<cmp-field-mapping name="DeptBean_deptno"
persistence-name="DEPARTMENT" /></entity-ref>
</cmp-field-mapping>
</primkey-mapping>
<value-mapping
type="hr.EmpLocal">
<cmp-field-mapping name="EmpBean_empNo">
<entity-ref home="
EmpBean">
<cmp-field-mapping name="EmpBean_empNo"
persistence-name="EMPLOYEE" /></entity-ref>
</cmp-field-mapping>
</value-mapping>
</collection-mapping>
</cmp-field-mapping>
...
</entity-deployment> <entity-deployment name="EmpBean" location="EmpBean" 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="dept"> <entity-ref home="DeptBean"> <cmp-field-mapping name="dept" persistence-name="DEPARTMENT" /> </entity-ref> </cmp-field-mapping> ... </entity-deployment>
The following describes how the DeptBean
is configured in the orion-ejb-jar.xml
file:
The relationship from the department to the employee bean is defined in the employees
field, which is mapped in the <collection-mapping>
element.
The association table name is specified in the table
attribute, which currently defines the association table name as DEPT_EMP
.
The foreign keys of the association table are defined as follows:
The <primkey-mapping>
element defines the column name for the foreign key of the current entity bean in the persistence-name
attribute, which is DEPARTMENT
.
The <value-mapping>
element defines the column name for the foreign key of the target bean in the persistence-name
attribute, which is EMPLOYEE
.
The <value-mapping>
element specifies the target entity bean.
The type
attribute of the <value-mapping>
element defines the local interface of the target bean that is returned to the source entity bean.
The <ejb-name>
of the target entity bean is defined in the <entity-ref>
home
attribute.
The following describes how the EmpBean
is configured in the orion-ejb-jar.xml
file:
The relationship from the employee to the department bean is defined in the dept
field, which is mapped in the <cmp-field-mapping><entity-ref>
element. The persistence-name
attribute contains the foreign key in the association table that points to the department bean.
As described in "One-To-Many or Many-To-One Relationship Overview", one bean, such as an employee, can have a relationship to multiple instances of another bean, such as phone numbers. For each employee, you can have one or more phone numbers. However, this is a unidirectional relationship. You cannot look up an employee given a phone number.
The relationships between the EmpBean
and PhoneBean
is represented by a CMR field, phones
, as shown in Figure 6-17.
Figure 6-17 One-To-Many Unidirectional Bean Relationship
The relationship is mapped to database tables using an association table, which maps the two tables together appropriately. The association table consists of two foreign keys.
Note: If you have a composite primary key in either or both tables, the foreign key will be a composite foreign key; thus, the association table will have the appropriate number of columns for each part of the composite foreign key. |
For a full description of how an association table works, see "Example of a Default Mapping of One-To-Many and Many-To-Many Relationships". This section shows how to change the XML configuration for this mapping.
Note: If you do not want to use an association table, see "Using a Foreign Key with the One-To-Many Relationship" for directions on how to use a foreign key in the "one" side of the relationship. |
Figure 6-18 shows the employee—>phone numbers example, where each employee can have multiple phone numbers. Both the employee and phone tables have a primary key. A separate table, the association table, contains two foreign keys. One foreign key points to the employee; the other foreign key points to the phone number. Every relationship has its own row denoting the relationship. Thus, for every phone number, a row is created where the first foreign key points to the employee to which the phone number belongs and the second foreign key points to the phone number record. Figure 6-18 shows an association table, EMP_PHONE
, where the foreign keys are named EMPLOYEE
and PHONEBEAN_AUTOID
.
Figure 6-18 Explicit Mapping for One-to-Many Unidirectional Bean Relationship
To change the mappings to other database tables, then you use either JDeveloper or hand-edit the orion-ejb-jar.xml
file to manipulate the <collection-mapping>
or <set-mapping>
element.
Important: You modify elements and attributes of the<entity-deployment> element in the orion-ejb-jar.xml file to explicitly map relationship fields. JDeveloper was created to manage the complex mapping between the entity beans and the database tables. Thus, JDeveloper validates the deployment descriptors and prevents inconsistencies. You are allowed to modify the orion-ejb-jar.xml file on your own; however, we suggest that you use JDeveloper for modifying container-managed relationships. CMR configuration is complex and can be difficult to understand. You can download JDeveloper at the following site: http://www.oracle.com/technology/software/products/jdev/index.html .
|
In the ejb-jar.xml
file, the cardinality is defined in the <relationships>
element. The following is the ejb-jar.xml
file configuration of the one-to-many unidirectional example of the employee and his/her phone numbers.
The primary key field of the EmpBean
is empNo
, as defined in the <primkey-field>
element.
The primary key of the PhoneBean
is not defined, as defined by the absence of the <primkey-field>
element and the existence of the <prim-key-class>
element. Thus, the primary key is auto-generated and represented by AUTOID. For more information on auto-generated primary keys, see "Defining an Auto-Generated Primary Key for Your Entity Bean".
The CMR field (<cmr-field>
element) defining the "many" side of the relationship is a Collection
that is identified as phones
.
<entity> <ejb-name>EmpBean</ejb-name> ... <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>PhoneBean</ejb-name> ... <cmp-field><field-name>phoneNo</field-name></cmp-field> <cmp-field><field-name>phoneType</field-name></cmp-field> <prim-key-class>java.lang.Object</prim-key-class> ... </entity> <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>phones</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>
In the orion-ejb-jar.xml
file, the mapping of this relationship to an association table is described in a <collection-mapping>
element. The "one" side of the relationship, the employee, owns the "many" entities, the phone numbers; thus, the employee defines the <collection-mapping>
element that describes the relationship with the phone numbers. In all one-to-many relationships, the entity bean that is represents the "one" side of the relationship defines the <collection-mapping>
element as it receives back a Collection
or Set
of the target entity bean. The entity bean on the "many" side of the relationship defines a <cmp-field-mapping>
<entity-ref>
element that shows the relationship back to the entity bean that is the "one" side of the relationship. So, the employee defines the <collection-mapping>
element to define its relationship with the phone numbers: the phone numbers uses an <entity-ref>
element to define its relationship with the employee.
In the orion-ejb-jar.xml
file for the employee/phone numbers example, the EmpBean
<entity-deployment>
element defines the <collection-mapping>
element to designate a Collection
of phone numbers. The <collection-mapping>
element specifies the association table.
<entity-deployment name="
EmpBean" table="
EMP">
<primkey-mapping>
<cmp-field-mapping name="empNo" persistence-name="EMPLOYEENO" />
</primkey-mapping>
<cmp-field-mapping name="empName" persistence-name="EMPLOYEENAME" />
<cmp-field-mapping name="salary" persistence-name="SAL" />
<cmp-field-mapping name="
phones">
<collection-mapping table="EMP_PHONE"><primkey-mapping>
<cmp-field-mapping name="EmpBean_empNo">
<entity-ref home="
EmpBean">
<cmp-field-mapping name="EmpBean_empNo"
persistence-name="
EMPLOYEENO"/>
</entity-ref>
</cmp-field-mapping>
</primkey-mapping>
<value-mapping type="
hr.PhoneLocal">
<cmp-field-mapping name="PhoneBean_autoid">
<entity-ref home="
PhoneBean">
<cmp-field-mapping name="PhoneBean_autoid"
persistence-name="
AUTOID"/>
</entity-ref>
</cmp-field-mapping>
</value-mapping>
</collection-mapping>
...
</entity-deployment> <entity-deployment name="PhoneBean" table="PHONE"> <primkey-mapping> <cmp-field-mapping name="autoid" persistence-name="AUTOID"/> </primkey-mapping> <cmp-field-mapping name="phoneNo" persistence-name="PHONE_NO" /> <cmp-field-mapping name="phoneType" persistence-name="PHONE_TYPE" /> <cmp-field-mapping name="EmpBean_phones"> <entity-ref home="EmpBean"> <cmp-field-mapping name="EmpBean_phones" persistence-name="EMPLOYEENO" /> </entity-ref> </cmp-field-mapping> </entity-deployment>
The following describes how the EmpBean
is defined in the ejb-jar.xml
and orion-ejb-jar.xml
files. See Figure 6-18 for a graphic of this mapping.
The <cmr-field>
element in the ejb-jar.xml
file defines a name for the relationship with the phone numbers as phones
.
The phones
<cmr-field>
element maps to the association table in the orion-ejb-jar.xml
file. In the orion-ejb-jar.xml
file, the <cmp-field-mapping>
for phones
contains a <collection-mapping>
element. This <collection-mapping>
element defines the association table name in the table
attribute as EMP_PHONE
.
The association table has two foreign keys. In this example, the foreign keys are simple. However, if the primary keys are composite, then these foreign keys would be composite as well.
Both foreign keys for the association table are defined as follows:
The persistence-name
attribute in the <primkey-mapping>
element defines the association table foreign key column name of the current entity bean, which is EMPLOYEENO
.
The persistence-name
attribute in the <value-mapping>
element defines the association table foreign key column name of the target bean, which is PhoneBean_AUTOID
.
The <value-mapping>
element specifies the target entity bean.
The type
attribute of the <value-mapping>
element defines the local interface of the target bean that is returned to the source entity bean. This example defines the local home interface of the phone bean as hr.PhoneLocal
.
The <ejb-name>
of the target entity bean is defined in the <entity-ref>
home
attribute, which in this example is PhoneBean
.
The phone bean configuration in the orion-ejb-jar.xml
file defines an <entity-ref>
for a relationship to the employee bean.
The <ejb-name>
of the target entity bean is defined in the <entity-ref>
home
attribute, which in this example is EmpBean
.
The persistence-name
attribute in the <cmp-field-mapping>
element defines the association table foreign key of the current entity bean, which is EMPLOYEENO
.
Figure 6-19 shows the following:
How the CMR field name maps to the <cmp-field-mapping>
elements in the orion-ejb-jar.xml
file.
How the association table is defined by the <collection-mapping>
element in the employee bean definition.
Figure 6-19 Explicit Mapping for a One-to-Many Relationship
As described in "Many-To-Many Relationship Overview", many beans, such as employees, can have a relationship to multiple instances of another bean, such as projects. There are several employees in each project; each employee can be assigned to multiple projects. Since this is a bidirectional relationship, you can look up the project from the employee. The relationships between the ProjectBean
and EmpBean
is represented by CMR fields, employees
and projects
, as shown in Figure 6-20.
Figure 6-20 Many-to-Many Bidirectional Bean Relationship
This relationship is mapped to database tables using as an association table. The association table consists of two foreign keys.
Note: If you have a composite primary key in either or both tables, the foreign key will be a composite foreign key; thus, the association table will have the appropriate number of columns for each part of the composite foreign key. |
For a full description of how an association table works, see "Example of a Default Mapping of One-To-Many and Many-To-Many Relationships". This section shows how to change the XML configuration for this mapping.
Figure 6-21 shows the projects<—>employee example, where each employee belongs to one or more projects and each project can contain multiple employees. Both the project and employee tables have a primary key. A separate table, the association table, contains two foreign keys. One foreign key points to the project; the other foreign key points to the employee. Every relationship has its own row denoting the relationship. Thus, for every employee, a row is created where the first foreign key points to the project the employee belongs to and the second foreign key points to the employee record. The association table in Figure 6-21 shows an association table, PROJECT_EMP
, where the foreign keys are named PROJECT_NO
and EMPLOYEE_NO
.
Figure 6-21 Explicit Mapping for One-to-Many Bidirectional Relationship Example
If you need to change the mappings to other database tables, then you use either JDeveloper or hand-edit the orion-ejb-jar.xml
file to manipulate the <collection-mapping>
or <set-mapping>
element.
Important: You modify elements and attributes of the<entity-deployment> element in the orion-ejb-jar.xml file to explicitly map relationship fields. JDeveloper was created to manage the complex mapping between the entity beans and the database tables. Thus, JDeveloper validates the deployment descriptors and prevents inconsistencies. You are allowed to modify the orion-ejb-jar.xml file on your own; however, we suggest that you use JDeveloper for modifying container-managed relationships. CMR configuration is complex and can be difficult to understand. You can download JDeveloper at the following site: http://www.oracle.com/technology/software/products/jdev/index.html .
|
Example 6-10 XML Structure for Many-to-Many Relationship Mapping
The relationship that is defined in the ejb-jar.xml
file is mapped in the orion-ejb-jar.xml
file within a <cmp-field-mapping>
element. The <cmp-field-mapping>
element contains either a <collection-mapping>
or <set-mapping>
element. The project/employee example describes both sides of the "many" relationship with a <collection-mapping>
element; thus, both sides use a <collection-mapping>
to describe their side of the relationship, even though the information is the same on both sides.
In the ejb-jar.xml
file, both sides are define a "many" relationship to each other; thus, both sides declare the <multiplicity>
element as Many
and define a relationship to each other in a CMR field. The project bean defines the CMR field as employees
; the employee bean defines the CMR field as projects
. These CMR fields are used in the orion-ejb-jar.xml
file to map these relationships in the database tables.
<entity> ... <relationships> <ejb-relation> <ejb-relation-name>Emps-Projects</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name>Projects-have-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>Emps-have-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> ... </entity>
Then in the orion-ejb-jar.xml
file, both sides define the relationship with each other in a <collection-mapping>
element. This element defines the association table. An association table is created that contains two foreign keys, where each foreign key points to the primary key of the source and target tables. Thus, explicit mapping of this relationship requires modifying the association table name and its foreign key names. You must modify both <collection-mapping>
elements with the same information, because both <collection-mapping>
elements contain the same information about the association table. The only difference is that the information is switched in the <primary-key>
and <value-mapping>
elements in each bean definition. What is defined in the <primary-key>
element in the project bean definition will be defined in the <value-mapping>
element in the employee bean definition.
<entity-deployment name="
EmpBean" location="EmpBean" table="EmpBean_ormap_ormap_ejb" data-source="jdbc/OracleDS" >
... <entity-deployment name="EmpBean" table="EMP"> <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="projects"> <collection-mapping table="PROJECT_EMP"> <primkey-mapping> <cmp-field-mapping name="EmpBean_empNo"> <entity-ref home="EmpBean"> <cmp-field-mapping name="EmpBean_empNo" persistence-name="EMPLOYEE_NO" /> </entity-ref> </cmp-field-mapping> </primkey-mapping> <value-mapping type="hr.ProjectLocal"> <cmp-field-mapping name="ProjectBean_projectNo"> <entity-ref home="ProjectBean"> <cmp-field-mapping name="ProjectBean_projectNo" persistence-name="PROJECT_NO" /> </entity-ref> </cmp-field-mapping> </value-mapping> </collection-mapping> </cmp-field-mapping> ... </entity-deployment> ... <entity-deployment name="ProjectBean" location="ProjectBean" table="ProjectBean_ormap_ormap_ejb" data-source="jdbc/OracleDS" > <primkey-mapping> <cmp-field-mapping name="projectNo" persistence-name="PROJECTNO" /> </primkey-mapping> <cmp-field-mapping name="projectName" persistence-name="PNAME" /> <cmp-field-mapping name="employees"> <collection-mapping table="PROJECT_EMP"> <primkey-mapping> <cmp-field-mapping name="ProjectBean_projectNo"> <entity-ref home="ProjectBean"> <cmp-field-mapping name="ProjectBean_projectNo" persistence-name="PROJECT_NO" /> </entity-ref> </cmp-field-mapping> </primkey-mapping> <value-mapping type="hr.EmpLocal"> <cmp-field-mapping name="EmpBean_empNo"> <entity-ref home="EmpBean"> <cmp-field-mapping name="EmpBean_empNo" persistence-name="EMPLOYEE_NO" /> </entity-ref> </cmp-field-mapping> </value-mapping> </collection-mapping> </cmp-field-mapping>
The following describes the fields in the orion-ejb-jar.xml
file:
The project bean defines a <cmr-field>
element in the ejb-jar.xml
file defines a name for the relationship with employees as employees
; the employees <cmr-field>
element defines a name for the relationship with projects as projects
.
Both of the projects
and employees
<cmr-field>
elements map to the association table in the orion-ejb-jar.xml
file. In this file, each of the <cmp-field-mapping>
elements for projects
and employees
contain a <collection-mapping>
element. This <collection-mapping>
element defines the association table name in the table
attribute as PROJECT_EMP
.
The association has two foreign keys. In this example, the foreign keys are simple. However, if the primary keys are composite, then these foreign keys would be composite as well.
Both foreign keys in the EmpBean
for the association table are defined as follows:
The persistence-name
attribute in the <primkey-mapping>
element defines the association table foreign key of the current entity bean, which is EMPLOYEE_NO
.
The persistence-name
attribute in the <value-mapping>
element defines the association table foreign key of the target bean, which is PROJECT_NO
.
The <value-mapping>
element in EmpBean
specifies the target entity bean.
The type
attribute of the <value-mapping>
element defines the local interface of the target bean that is returned to the source entity bean. This example defines the local home interface of the phone bean as hr.ProjectLocal
.
The <ejb-name>
of the target entity bean is defined in the <entity-ref>
home
attribute, which in this example is ProjectBean
.