Skip Headers

Oracle® Containers for J2EE Orion CMP Developer's Guide 10g Release 3 (10.1.3) B19177-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# Configuring Container-Managed Relationship Fields

A relationship field identifies a related bean. A relationship field behaves similar to a foreign key in a database table. For more information, see "Relationship Fields".

Relationship fields are virtual. You provide getters and setters for these fields in the code of your bean class, similar to the following:

    public abstract void setContractInfo(ContractInfo contractInfo) throws RemoteException

    public abstract ContractInfo getContractInfo() throws RemoteException

The container provides the implementation of these methods.

In the preceding example, the corresponding relationship field is `contractInfo`.

In a deployment descriptor, this field is defined in a `<cmr-field><cmr-field-name>` element, as follows:

    <ejb-ralation>
        ...
        <cmr-field>
            <cmr-field-name>contractInfo</cmr-field-name>
            <cmr-field-type>contractInfo</cmr-field-type>
        </cmr-field>
        ...
    </ejb-ralation>

For more information about container-managed relationships, see "Container-Managed Relationships".

As each entity bean maps to a table in a database, each of its persistent and relationship fields are saved within a database table in columns. You can map these fields to the database by performing one of the following:

- Accept the defaults for these fields. Do not configure the deployment descriptor. The tables are automatically created for the bean based on the information in the `ejb-jar.xml` file. See "Configuring Default Mapping of Relationship Fields to the Database" for more information.

- Map these 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 "Configuring Explicit Mapping of Relationship Fields to the Database" for more information.

## Configuring Default Mapping of Relationship Fields to the Database

When you declare relationship fields in the `ejb-jar.xml` file, OC4J provides default mapping of these fields to the database at the time of the automatic generation of the `orion-ejb-jar.xml` file. The default mapping for relationship fields is the same as for the persistent fields (see "Configuring Default Mapping of Persistent Fields to the Database").

Note: For all future redeployments, copy the automatically generated `orion-ejb-jar.xml` file with the indicated table name into the same directory as your `ejb-jar.xml` file from the `J2EE_Home/application-deployments` directory. If you fail to do so, different table names may be generated at each redeployment.

In summary, the default mappings include the following:

- 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 underlying database table. The name of the entity bean's underlying table is supposed to be unique, so it is constructed with the following names, where each entry is separated by an underscore character ( _ ):

  - EJB name defined in a `<ejb-name>` element in the deployment descriptor;

  - JAR file name, including the`.jar` extension. However, all dash characters ( - ) and periods ( . ) are converted to underscore characters ( _ ) to follow SQL conventions. For example, if the name of your JAR file is `address.jar`, then `address_jar` is appended to the name;

  - Application name as defined by you during the deployment.

  If the constructed name is greater than 30 (thirty) characters, the name is truncated at 24 (twenty-four) characters. An underscore character ( _ ), and then 5 (five) characters made up of an alpha-numeric hash code are appended to the name for uniqueness.

  For example, if the EJB name is `AddressEntry`, the JAR file name is `addr.jar` and the application name is `address`, then the default table name would be `AddressEntry_addr_jar_address`.

- 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 (see "Direction in CMR"), only a single entity in the relationship defines a `<cmr-field>` in the deployment descriptor. In bidirectional relationship (see "Direction in CMR"), 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 entity bean, 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.

  - The default for one-to-many relationship uses a foreign key.

  - The default for many-to-many relationships creates an association table (a third table). This association table contains two foreign keys, where each key points to the primary key of one of the entity tables.

  Since the `<cmp-field>` and `<cmr-field>` elements represent Java data types, they may not convert to database types in the manner you believe they should. There is a set of rules for converting CMP types to database types that you must follow (see "Conversion of CMP Types to Database Types"). Note that you can modify the translation rules of converting Java data types to database data types in special database XML files that are located in `J2EE_HOME/config/database-schemas` directory. This directory includes all database files. The Oracle Database conversion file is named `oracle.xml`.

- Primary keys–Entity beans' underlying tables contain primary keys (see "Configuring Primary Key"). The following are the types of primary keys:

  - Defined primary key: The primary key is generated as designated in the `<primkey-field>` element as a simple data type or 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 composed of several fields. Each field within the composite primary key is represented by a column in the database table, where each field is considered part of the primary key in the table.

  - Automatically generated primary key: If you specify a`java.lang.Object` as the primary key class type in `<prim-key-class>` element, but do not specify the primary key name in `<primkey-field>` element, then the primary key is automatically generated the the container. The column is named `AUTOID`.

### Conversion of CMP Types to Database Types

In defining the container-managed persistent fields in the `<cmp-field>` and the primary key types, you can define simple data types and Java classes that are serializable.

This section contains information on the following:

- Simple Data Types

- Serializable Classes

- Other Entity Beans or Collections

#### Simple Data Types

Table 5-4 provides a list of the supported simple data types, which you can provide in the `persistence-type` attribute, with the mapping of these types to SQL types and to Oracle database types. Note that none of these mappings are guaranteed to work on non-Oracle databases.

Table 5-4 Simple Data Types

Known Type (native) | SQL Type | Oracle Type
--- | --- | ---
java.lang.String | VARCHAR(255) | VARCHAR(255)
java.lang.Integer[] | INTEGER | NUMBER(20,0)
java.lang.Long[] | INTEGER | NUMBER(20,0)
java.lang.Short[] | INTEGER | NUMBER(10,0)
java.lang.Double[] | DOUBLE PRECISION | NUMBER(30,0)
java.lang.Float[] | FLOAT | NUMBER(20,5)
java.lang.Byte[] | SMALLINT | NUMBER(10,0)
java.lang.Character[] | CHAR | CHAR(1
java.lang.Boolean[] | BIT | NUMBER(1,0)
java.util.Date | DATETIME | DATE
java.sql.Date | DATE | DATE
java.uti.Time | DATE | DATE
java.sql.Timestamp | TIMESTAMP | TIMESTAMP
java.lang.String | CLOB | CLOB
char[] | CLOB | CLOB
byte[] | BLOB | BLOB
java.io.Serializable (4KB limit) | LONGVARBINARY | BLOB

Note: You can modify the mapping of these data types in the `config/database-schema/<db>.xml` configuration files.

The `Date` and `Time` map to `DATE` in the database, because the `DATE` contains the time. The `Timestamp`, however, maps to `TIMESTAMP` in the database, which gives the time in nanoseconds.

Mapping `java.sql.CLOB` and `java.sql.BLOB` directly is not currently supported because these objects are not serializable. However you can map a `String` or `char[]` and `byte[]` to database column type `CLOB` and `BLOB` respectively. Mapping a `char[]` to a `CLOB` or a `byte[]` to a `BLOB` can only be done with an Oracle database. The Oracle JDBC API was modified to handle this operation.

There is a 4 KB limit when mapping a serialized object to a `BLOB` type over the JDBC Thin driver.

When `String` and `char[]` variables map to a `VARCHAR2` in the database, it can only hold up to 2K. However, you can map `String` object or `char[]` larger than 2K to a `CLOB` by doing the following:

1. The bean implementation uses the `String` or `char[]` objects.

2. The `persistence-type` attribute of the `<cmp-field-mapping>` element defines the object as a `CLOB`, as follows:

       <cmp-field-mapping name="stringdata" persistence-name="stringdata"
                                            persistence-type="CLOB" />

Similarly, you can map a `byte[]` in the bean implementation to a `BLOB`, as follows:

    <cmp-field-mapping name="bytedata" persistence-name="bytedata"
                                       persistence-type="BLOB" />

#### Serializable Classes

In addition to simple data types, you can define user classes that implement `java.io.Serializable` interface. These classes are stored in a `BLOB` in the database.

#### Other Entity Beans or Collections

You should not define other entity beans or `Collection` objects as a CMP type–these are relationships and should be defined within a relationship field, as follows:

- A relationship to another entity bean is always defined in a `<cmr-field>` relationship.

- `Collection` objects promote a "many" side of a relationship and should be configured within a `<cmr-field>` relationship.

  Note: You should not use subinterfaces of `Collection` (such as `List`, for example). Use the `Collection` instead.

## Configuring Explicit Mapping of Relationship Fields to the Database

As "Configuring Default Mapping of Persistent Fields to the Database" discusses, the container can automatically map your relationship fields to the database tables. 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 manually map the relationships between entity beans to an existing database table and its columns in the `orion-ejb-jar.xml` file.

Note: You need to modify elements and attributes of the `<entity-deployment>` element t (see Table A-1, "Attributes of the <entity-deployment> Element") in the `orion-ejb-jar.xml` file to explicitly map relationship fields. JDeveloper IDE is capable of managing complex mappings between the entity beans and the database tables. Thus, JDeveloper validates the deployment descriptors and prevents inconsistencies. You can modify the `orion-ejb-jar.xml` file on your own; however, Oracle suggests that you use JDeveloper for modifying container-managed relationships. For more information about JDeveloper, see "Using JDeveloper".

To manually match an existing database to the entity bean's mappings, modify the `orion-ejb-jar.xml` file by following this procedure:

1. Deploy your entity bean with container-managed persistence with the `<autocreate-tables>` element set to `false` in the `orion-application.xml` file.

2. Copy the `orion-ejb-jar.xml` file from the `application-deployments/` directory to your development directory.

3. Modify the `<data-source>` element to point to the correct data source. Note that all beans that are associated with each other must use the same data source.

4. Modify the `table` attribute to point to the correct table. Make sure that it is the correct table for the bean that is defined in the `<entity-deployments>` element.

5. Modify the `persistence-name` attributes to point to the correct column for each bean's persistence type, whether a persistent or relationship field.

6. Set the `<autocreate-tables>` element in `orion-application.xml` file to `true`.

7. Rearchive and redeploy your application.

To manually modify mapping elements if there is no existing database to match to your entity bean's mappings, follow this procedure:

1. 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 with the default mappings in it. It is easier to modify these fields than to create them.

2. Copy the container-created `orion-ejb-jar.xml` file from the `J2EE_HOME/application-deployments` directory to your development environment.

3. Modify the `<entity-deployment>` element (see Table A-1, "Attributes of the <entity-deployment> Element") in the `orion-ejb-jar.xml` file to use the database table and columns that you specify based on the relationship type. For more information, see"Configuring orion-ejb-jar.xml to Map Bean Relationships to Database Tables".

4. Set the `<autocreate-tables>` element in `orion-application.xml` file to `true`.

5. Rearchive and redeploy your application.

   Note: If you deploy your application without setting `<autocreate-tables>` to `false`, then OC4J automatically creates the default tables. You must delete all these tables before redeploying the application. You must also delete an association table, if any.

### Configuring orion-ejb-jar.xml to Map Bean Relationships to Database Tables

The relationship between the entity beans is defined in the `<relationships>` element in the `ejb-jar.xml file`. The mapping between the entity 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 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 the `<cmp-field-mapping>` element, you can define the bean's 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 persistent and relationship fields defined in the `ejb-jar.xml` file to the underlying database.

The attributes of the `<entity-deployment>` element (see Table A-1, "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 persistent field.

- The `<cmr-field>` element in the `ejb-jar.xml` file defines a relationship field.

Example 5-6 ejb-jar.xml and orion-ejb-jar.xml Mapping for a One-To-One Relationship

Example 5-6 demonstrates 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.

`EJB-JAR.XML`

    <relationship-role-source>
        <ejb-name>EmpBean</ejb-name>
    </relationship-role-source>
    <cmr-field>
        <cmr-field-name>address</cmr-field-name>
    </cmr-field>

`ORION-EJB-JAR.XML`

    <cmp-field-mapping name="address">
        <entity-ref home="AddressBean">
            <cmp-field-mapping name="address" persistence-name="addressPK" />
        </entity-ref>
    </cmp-field-mapping>

To fully identify and map relationship 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.

### Explicit One-to-One Relationship Mapping

In a hypothetical model, there is a one-to-one unidirectional relationship (see "Direction in CMR") between a single employee (represented by `EmpBean`) and his/her address (represented by `AddressBean`). The `EmpBean` points to the `AddressBean` using the relationship field `address`. These two beans will map to the `EMP` and `ADDRESS` database tables. The `EMP` table has a foreign key named `address`, which points to the primary key of the `ADDRESS` table named `AddressPK`.

Example 5-7 Explicit One-to-One Unidirectional Relationship Mapping

The beans and their relationships are specified in both the `ejb-jar.xml` and the `orion-ejb-jar.xml` deployment descriptors. As Example 5-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 (see "Direction in CMR") 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 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.

`EJB-JAR.XML`

    <relationships>
    ...
        <ejb-relation>
        ...
        <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-relation>
        <ejb-relation>
        ...
            <relationship-role-source>
                <ejb-name>AddressBean</ejb-name>
            </relationship-role-source>
            ...
        </ejb-relation>
    ...

`ORION-EJB-JAR.XML`

    <entity-deployment name="EmpBean"...

        <cmp-field-mapping name="address">
            <entity-ref home="AddressBean">
                <cmp-field-mapping name="address" persistentce-name="addressPK" />
            </entity-ref>
        </cmp-field-mapping>
        ...
    </entity-deployment>
    <entity-deployment name="AddressBean"...
        ...
        <cmp-field-mapping name="empNumber">
            <entity-ref home="EmpBean">
                <cmp-field-mapping name="empNumber" persistentce-name="empnumber" />
            </entity-ref>
        </cmp-field-mapping>
        ...
    </entity-deployment>

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>

In the preceding structure example, the following occurs:

- The name attribute of the `<cmp-field-mapping>` element is the same as the `<cmp-field>` element in the e`jb-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.

### Explicit One-to-Many Relationship Mapping

In a hypothetical model, each employee (represented by `EmpBean`) belongs to only one department (represented by `DeptBean`), 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 executes a `JOIN` statement on both the department and employee tables and retrieves all employees with the designated department number.

This is the default behavior. If you need to change the mappings to other database tables, then use either JDeveloper, or manually modify the `orion-ejb-jar.xml` file to manipulate the `<collection-mapping>` or `<set-mapping>` element.

Note: Modify elements and attributes of the `<entity-deployment>` element (see Table A-1, "Attributes of the <entity-deployment> Element") in the `orion-ejb-jar.xml` file to explicitly map relationship fields. JDeveloper is capable of managing the complex mapping between the entity beans and the database tables. JDeveloper validates the deployment descriptors and prevents inconsistencies. Even though you can modify the `orion-ejb-jar.xml` file on your own, Oracle suggests you to use JDeveloper for modifying container-managed relationships. For more information about JDeveloper, see "Using JDeveloper".

Example 5-8 Explicit One-to-Many Bidirectional Relationship Mapping Using Foreign Key

Example 5-8 shows the 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. Example 5-8 demonstrates how to manually modify the `orion-ejb-jar.xml` file for this relationship to use a foreign key.

`EJB-JAR.XML`

    <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-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>

`ORION-EJB-JAR.XML`

    <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 with FK*/
                <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_empnumber">
                        <entity-ref home="EmpBean">
                            <cmp-field-mapping name="EmpBean_empnumber"
                            persistence-name="EMPNUMBER"/>
                        </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="empNumber" persistence-name="EMPNUMBER"/>
            </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>

In the preceding `orion-ejb-jar.xml` example, 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`.

The foreign key is defined in the database table of the "many" relationship. In the preceding 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 (see Table A-1, "Attributes of the <entity-deployment> Element") for the "one" entity bean (which contains the `Collection`), as follows:

1. 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.

2. 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.