Skip Headers

Oracle® Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide 10g Release 2 (10.1.2) Part No. B15505-02 |
| Library |  | Contents | Index

Previous | Next |

# 4 CMP Entity Beans

This chapter demonstrates simple Container Managed Persistence (CMP) EJB development with a basic configuration and deployment. Download the CMP entity bean example (`cmpapp.jar`) from the OC4J sample code page at on the OTN Web site.

This chapter demonstrates the following:

- Persistence Fields

- Configuring Lazy Loading on CMP Entity Bean Finder Methods

- Conversion of CMP Types to Database Types

See Chapter 8, "BMP Entity Beans", for an example of how to create a simple bean-managed persistent entity bean. For a description of persisting object relationships between EJBs, see Chapter 6, "Entity Relationship Mapping".

## Persistence Fields

The persistent data in your CMP bean can be one of the following:

- Persistence field—Simple data type that is persisted to a database table. This field is a direct attribute of the bean.

- Relationship field—Relationship to another bean.

Each type results in its own complex rules of how to configure. This section discusses persistence fields. For information on relationship fields, see Chapter 6, "Entity Relationship Mapping".

In CMP entity beans, you define the persistent data both in the bean instance and in the deployment descriptor.

- Get/Set methods in the bean instance: For each persistence and relationship field, both a get and a set method is created. For persistence fields, the data type of the parameter returned from the get method and passed into the set method defines the simple data type of the field. The name of the field is designated by the name of the get and set methods.

  The following XML shows the get and set methods for the employee name persistence field. A `String` is passed back from the get method and into the set method. Thus, the `String` is the simple data type of the field. If you remove the "get" and "set" from the method names and then lower the case of the first letter, you have the persistence field name. In this case, `empName` is the persistence field name.

      public abstract String getEmpName() throws RemoteException;
      public abstract void setEmpName(String empName) throws RemoteException;

- The deployment descriptor defines these fields as persistent. Each field name must be defined in a `<cmp-field><field-name>` element in the EJB deployment descriptor. In the employee example, three persistence data fields are defined in the data accessor methods: `empNo`, `empName`, and `salary`.

  These fields are defined as persistent fields in the `ejb-jar.xml` deployment descriptor within the `<cmp-field><field-name>` element, as follows:

      <enterprise-beans>
            <entity>
               <display-name>Employee</display-name>
               <ejb-name>EmployeeBean</ejb-name>
               <local-home>employee.EmployeeLocalHome</local-home>
               <local>employee.EmployeeLocal</local>
               <ejb-class>employee.EmployeeBean</ejb-class>
               <persistence-type>Container</persistence-type>
               <prim-key-class>java.lang.Integer</prim-key-class>
               <reentrant>False</reentrant>
               <cmp-version>2.x</cmp-version>
               <abstract-schema-name>Employee</abstract-schema-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>
            </entity>
      ...
      </enterprise-beans>

For these fields to be mapped to a database, you can do one of the following:

- Accept the defaults for these fields and avoid more deployment descriptor configuration. See "Default Mapping of Persistent Fields to the Database" on how the default mapping occurs.

- Map the persistent data fields to columns in a table that exists in a designated database. The persistent data mapping is configured within the `orion-ejb-jar.xml` file. See "Explicit Mapping of Persistent Fields to the Database" for more information.

  Note: The entire CMP entity bean example (`cmpapp.jar`) is available on OTN from the OC4J sample code page at `http://www.oracle.com/technology/tech/java/oc4j/demos/` on the OTN Web site.

### Default Mapping of Persistent Fields to the Database

If you simply define the persistent fields in the `ejb-jar.xml` file, then OC4J provides the following mappings of these fields to the database:

- Database—The default database as set up in your OC4J instance configuration. For the JNDI name, use the `<location>` element for emulated data sources and `<ejb-location>` element for non-emulated data sources.

  Upon installation, the default database is a locally installed Oracle database that must be listening on port 1521 with a SID of `ORCL`. To customize the default database, change the first configured database to point to your database.

  Note: See the Data Source chapter in the Oracle Application Server Containers for J2EE Services Guide for more information on configuring Data Source objects.

- Table—The container automatically creates a default table where the name of the table is guaranteed to be unique. For all future redeployments, copy the generated `orion-ejb-jar.xml` file with this table name into the same directory as your `ejb-jar.xml` file. 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.

  The table name 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: This is the name of the application name, which you define during deployment.

  If the constructed name is greater than thirty characters, the name is truncated at twenty-four characters. Then six characters made up of an alphanumeric hash code is appended to the name.

  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—The columns in the entity bean table each have the same name as the `<cmp-field>` elements in the designated database. The data types for the database, translating Java data types to database data types, are defined in the specific database XML file, such as `oracle.xml`.

  Note: Auto-creation of tables in third-party databases may fail for certain data types unless the persistent-type mapping for VARCHAR is defined in the `orion-ejb-jar.xml` as follows: `<cmp-field-mapping name="../" persistence-name="..." persistence-type="varchar(10)" />`

### Explicit Mapping of Persistent Fields to the Database

As "Default Mapping of Persistent Fields to the Database" discusses, your persistent data can be automatically mapped to a database table by the container. However, if the data represented by your bean is more complex or you do not want to accept the defaults that OC4J provides for you, then you can map the persistent data to an existing database table and its columns within the `orion-ejb-jar.xml` file. Once the fields are mapped, the container provides the persistence storage of the persistent data to the indicated table and rows.

For explicit mapping, Oracle recommends that you do the following:

1. Deploy your application with only the `ejb-jar.xml` elements configured.

   OC4J creates an `orion-ejb-jar.xml` file for you with the default mappings in them. It is easier to modify these fields than to create them from scratch. This provides you a method for choosing all or part of the modifications that are discussed in this section.

2. Modify the `<entity-deployment>` element in the `orion-ejb-jar.xml` file to use the database table and columns you specify.

Once you define persistent fields, each within its own `<cmp-field>` element, you can map each to a specific database table and column. Thus, you can map CMP fields to existing database tables. The mapping occurs with the OC4J-specific deployment descriptor: `orion-ejb-jar.xml`.

The explicit mapping of CMP fields is completed within an `<entity-deployment>` element. This element contains all mapping for an entity bean. However, the attributes and elements that are specific to CMP field mapping is as follows:

    <entity-deployment name="..." location="..." 	table="..." data-source="...">
    	<primkey-mapping>
    		<cmp-field-mapping name="..." persistence-name="..." />
    	</primkey-mapping>
    	<cmp-field-mapping name="..." persistence-name="..." />
    ...
    </entity-deployment>

Element or Attribute Name | Description
--- | ---
`name` | Bean name, which is defined in the `ejb-jar.xml` file in the `<ejb-name>` element.
`location` | JNDI location
`table` | Database table name
`data-source` | Data source for the database where the table resides
`primkey-mapping` | Definition of how the primary key is mapped to the table.
`cmp-field-mapping` | The `name` attribute specifies the `<cmp-field>` in the deployment descriptor, which is mapped to a table column in the `persistence-name` attribute.

You can configure the following within the `orion-ejb-jar.xml` file:

1. Configure the `<entity-deployment>` element for every entity bean that contains CMP fields that will be mapped within it.

2. Configure a `<cmp-field-mapping>` element for every field within the bean that is mapped. Each `<cmp-field-mapping>` element must contain the name of the field to be persisted.

   1. Configure the primary key in the `<primkey-mapping>` element contained within its own `<cmp-field-mapping>` element.

   2. Configure simple data types (such as a primitive, simple object, or serializable object) that are mapped to a single field within a single `<cmp-field-mapping>` element. The name and database field are fully defined within the element attributes.

Example 4-1 Mapping Persistent Fields to a Specific Database Table

The following example demonstrates how to map persistent data fields in your bean instance to database tables and columns by mapping the employee persistence data fields to the Oracle database table `EMP`.

- The bean is identified in the `<entity-deployment>` `name` attribute. The JNDI name for this bean is defined in the `location` attribute.

- The database table name is defined in the `table` attribute. And the database is specified in the `data-source` attribute, which should be identical to the `<ejb-location>` name of a `DataSource` defined in the `data-sources.xml` file.

- The bean primary key, `empNo`, is mapped to the database table column, `EMPNO`, within the `<primkey-mapping>` element.

- The bean persistent data fields, `empName` and `salary`, are mapped to the database table columns `ENAME` and `SAL` within the `<cmp-field-mapping>` element.

    <entity-deployment name="EmpBean" location="emp/EmpBean"	wrapper="EmpHome_EntityHomeWrapper2" max-tx-retries="3" 	table="emp" data-source="jdbc/OracleDS">
    	<primkey-mapping>
    		<cmp-field-mapping name="empNo" persistence-name="empno" />
    	</primkey-mapping>
    	<cmp-field-mapping name="empName" persistence-name="ename" />
    	<cmp-field-mapping name="salary" persistence-name="sal" />
      ...
    </entity-deployment>

After deployment, OC4J maps the element values to the following:

Bean | Database
--- | ---
`emp/EmpBean` | EMP table, located at `jdbc/OracleDS` in the `data-sources.xml` file
`empNo` | `EMPNO` column as primary key
`empName` | `ENAME` column
`salary` | `SAL` column

## Configuring Lazy Loading on CMP Entity Bean Finder Methods

Each finder method retrieves one or more objects. In the default scenario (which is set to NO lazy loading), the finder method causes a single SQL select statement to be executed against the database. For a CMP bean, one or more objects are retrieved with all of their CMP fields. So, for example, with the `findAllEmployees` method, this finder retrieves all employee objects with all of the CMP fields in each employee object.

If you turn on lazy loading, then only the primary keys of the objects retrieved within the finder are returned. Then, only when you access the object within your implementation, the OC4J container uploads the actual object based on the primary key. With the `findAllEmployees` finder method example, all of the employee primary keys are returned in a `Collection`. The first time you access one of the employees in the `Collection`, OC4J uses the primary key to retrieve the single employee object from the database. You may want to turn on the lazy loading feature if the number of objects that you are retrieving is so large that loading them all into your local cache would be a performance degradation.

You have a performance consideration with lazy loading. If you retrieve multiple objects, but you only use a few of them, then you should turn on lazy loading. In addition, if you only use objects through the `getPrimaryKey` method, then you should also turn on lazy loading.

To turn on lazy loading in the `findByPrimaryKey` method, set the `findByPrimaryKey-lazy-loading` attribute to true, as follows:

    <entity-deployment ... findByPrimaryKey-lazy-loading="true" ... >

To turn on lazy loading in any custom finder method, set the lazy-loading attribute to true in the `<finder-method>` element for that custom finder, as follows:

    <finder-method ... lazy-loading="true" ...>
     ...
    </finder-method>

## 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 user classes that are serializable.

- Simple Data Types

- Serializable Classes

- Other Entity Beans or Collections

### Simple Data Types

The following table 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. None of these mappings are guaranteed to work on non-Oracle databases.

Table 4-1 Simple Data Types

Known Type (native) | SQL type | Oracle type
--- | --- | ---
java.lang.String | VARCHAR(255) | VARCHAR2(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.util.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` 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" />

In the same manner, 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 `Serializable`. These classes are stored in a BLOB in the database.

### Other Entity Beans or Collections

You should not define other entity beans or `Collections` as a CMP type. Instead, these are relationships and should be defined within a CMR field.

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

- `Collections` promote a "many" relationship and should be configured within a `<cmr-field>` relationship. Other types, such as `Lists`, are sub-interfaces of `Collections`. Oracle recommends that you use `Collections`.