Skip Headers
Oracle® Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide
10g Release 2 (10.1.2)
Part No. B15505-02
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
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:

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:

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.


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

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

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.