Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java System Application Server Platform Edition 2004Q4 Beta Developer's Guide 

Chapter 8
Using Container-Managed Persistence for Entity Beans

This section contains information on how container-managed persistence (CMP) works in the Sun Java System Application Server in the following topics:

Extensive information on CMP is contained in chapters 10, 11, and 14 of the Enterprise JavaBeans Specification, v2.1.


Sun Java System Application Server Support

Sun Java System Application Server support for CMP includes:


Container-Managed Persistence Mapping

Implementation for entity beans that use CMP is mostly a matter of mapping CMP fields and CMR fields (relationships) to the database. This section addresses the following topics:

The Mapping Deployment Descriptor File

Each module with CMP beans must have the following files:

The sun-cmp-mappings.xml file maps CMP fields and CMR fields (relationships) to the database. A primary table must be selected for each CMP bean, and optionally, multiple secondary tables. CMP fields are mapped to columns in either the primary or secondary table(s). CMR fields are mapped to pairs of column lists (normally, column lists are the lists of columns associated with primary and foreign keys).


Note

Table names in databases are case-sensitive. Make sure that the table names in the sun-cmp-mappings.xml file match the names in the database.


The sun-cmp-mappings.xml file conforms to the sun-cmp-mapping_1_2.dtd file and is packaged with the user-defined bean classes in the EJB JAR file under the META-INF directory.

The Sun Java System Application Server or the deploytool creates the mappings in the sun-cmp-mappings.xml file automatically during deployment if the file is not present. For information on how to use the deploytool for mapping, see the deploytool online help.

Automatic generation of the sun-cmp-mappings.xml file can be controlled by deployment options specified in the sun-ejb-jar.xml file and during deployment (see Automatic Mapping Options). To use automatic mapping, you only need to understand the Java programming language objects; you do not need to know or understand the underlying database schema.

To map the fields and relationships of your entity beans manually, edit the sun-cmp-mappings.xml deployment descriptor. Only do this if you are proficient in editing XML.

For a listing of the mapping elements in the CMP deployment descriptors and a sample XML file, see “The sun-cmp-mappings.xml File” on page 134.

The mapping information is developed in conjunction with the database schema (.dbschema) file, which can be automatically captured when you deploy the bean (see Capturing the Database Schema Automatically). You can manually generate the schema using the capture-schema utility (Using the capture-schema Utility).

Mapping Capabilities

Mapping refers to the ability to tie an object-based model to a relational model of data, usually the schema of a relational database. The CMP implementation provides the ability to tie a set of interrelated beans containing data and associated behaviors to the schema. This object representation of the database becomes part of the Java application. You can also customize this mapping to optimize these beans for the particular needs of an application. The result is a single data model through which both persistent database information and regular transient program data are accessed.

The mapping capabilities provided by the Sun Java System Application Server include:

Capturing the Database Schema Automatically

You can configure a CMP bean in Sun Java System Application Server to automatically capture the database metadata and save it in a .dbschema file during deployment. If the sun-cmp-mappings.xml file contains an empty <schema/> entry, the cmp-resource entry in the sun-ejb-jar.xml file is used to get a connection to the database, and automatic generation of the schema is performed. When the sun-cmp-mappings.xml file is itself automatically generated, it contains the <schema/> entry by default. If the database table structure is changed, you must redeploy the beans to automatically remap the CMP fields and relationships.

Table 8-5 shows how JDBC data types are mapped to database-specific types.


Note

Before capturing the database schema automatically, make sure you have properly configured a persistence manager. See Configuring the Persistence Manager.

For a read-only bean, do not create the database schema during deployment. Instead, work with your database administrator to populate the data into the tables. See “Using Read-Only Beans” on page 265.


Automatic Mapping Options

Deployment descriptor elements or command line options can control automatic mapping by:

The following optional data subelements of the cmp-resource element in the sun-ejb-jar.xml file control the automatic creation of database tables at deployment. For more information about the cmp-resource element, see Configuring the Persistence Manager.

Table 8-1  sun-ejb-jar.xml Mapping Elements

Element

Default

Description

create-tables-at-deploy

false

If true, causes database tables to be created for beans that are automatically mapped by the EJB container. If false, does not create tables.

drop-tables-at-undeploy

false

If true, causes database tables that were automatically created when the bean(s) were last deployed to be dropped when the bean(s) are undeployed. If false, does not drop tables.

database-vendor-name

none

Specifies the name of the database vendor for which tables are created. Allowed values are db2, mssql, oracle, pointbase, and sybase, case-insensitive.

If no value is specified, a connection is made to the resource specified by the jndi-name subelement of the cmp-resource element in the sun-ejb-jar.xml file, and the database vendor name is read. If the connection cannot be established, or if the value is not recognized, SQL-92 compliance is presumed.

schema-generator-properties

none

Specifies field-specific type mappings in property subelements.

Also allows you to set the use-unique-table-names property. If true, this property specifies that generated table names are unique within each application server domain. The default is false.

For example:

<schema-generator-properties>
  <property>
    <name>
      Employee.firstName.jdbc-type
    </name>
    <value>char</value>
  </property>
  <property>
    <name>
    Employee.firstName.jdbc-maximum-length
    </name>
    <value>25</value>
  </property>
  <property>
    <name>
      use-unique-table-names
    </name>
    <value>true</value>
  </property>
</schema-generator-properties>

The following options of the asadmin deploy or asadmin deploydir command control the automatic creation of database tables at deployment:

Table 8-2  asadmin deploy and asadmin deploydir Mapping Options

Option

Default

Description

--createtables

none

If true, causes database tables to be created for beans that need them. If false, does not create tables. If not specified, the value of the create-tables-at-deploy attribute in sun-ejb-jar.xml is used.

--dropandcreatetables

none

If true, and if tables were automatically created when this application was last deployed, tables from the earlier deployment are dropped and fresh ones are created.

If true, and if tables were not automatically created when this application was last deployed, no attempt is made to drop any tables. If tables with the same names as those that would have been automatically created are found, the deployment proceeds, but a warning indicates that tables could not be created.

If false, settings of create-tables-at-deploy or drop-tables-at-undeploy in the sun-ejb-jar.xml file are overridden.

--uniquetablenames

none

If true, specifies that table names are unique within each application server domain. If not specified, the value of the use-unique-table-names property in sun-ejb-jar.xml is used.

--dbvendorname

none

Specifies the name of the database vendor for which tables are created. Allowed values are db2, mssql, oracle, pointbase, and sybase, case-insensitive.

If not specified, the value of the database-vendor-name attribute in sun-ejb-jar.xml is used.

If no value is specified, a connection is made to the resource specified by the jndi-name subelement of the cmp-resource element in the sun-ejb-jar.xml file, and the database vendor name is read. If the connection cannot be established, or if the value is not recognized, SQL-92 compliance is presumed.

If one or more of the beans in the module are manually mapped and you use any of the asadmin deploy or asadmin deploydir options, the deployment is not harmed in any way, but the options have no effect, and a warning is written to the server log.

If the deploytool mapped one or more of the beans, the --uniquetablenames option of asadmin deploy or asadmin deploydir has no effect. The uniqueness of the table names was established when deploytool created the mapping.

The following options of the asadmin undeploy command control the automatic removal of database tables at undeployment:

Table 8-3  asadmin undeploy Mapping Options

Option

Default

Description

--droptables

none

If true, causes database tables that were automatically created when the bean(s) were last deployed to be dropped when the bean(s) are undeployed. If false, does not drop tables.

If not specified, the value of the drop-tables-at-undeploy attribute in sun-ejb-jar.xml is used.

For more information about the asadmin deploy, asadmin deploydir, and asadmin undeploy commands, see the Sun Java System Application Server Utility Reference.

When command line and sun-ejb-jar.xml options are both specified, the asadmin options take precedence.

Using the capture-schema Utility

You can use the capture-schema command to manually generate the database metadata (.dbschema) file.


Note

An Oracle database user running the capture-schema command needs ANALYZE ANY TABLE privileges if that user does not own the schema. These privileges are granted to the user by the database administrator.

The capture-schema utility does not modify the schema in any way. Its only purpose is to provide the persistence engine with information about the structure of the database (the schema).

The name of a .dbschema file must be unique across all deployed modules in a domain.


Syntax

capture-schema -username name -password password -dburl url -driver jdbcdriver -out filename [-schemaname schemaname] [-table tablename]*

Where:


Note

If more than one schema is accessible for this user, more than one table with the same name might be captured if this parameter is not set.

The schema name must be upper case.


Example

capture-schema -dburl jdbc:pointbase:server://localhost:9092/sample -username public -password public -driver com.pointbase.jdbc.jdbcUniversalDriver -out RosterSchema.dbschema

Join Tables and Relationships

Use of join tables in the database schema is supported for all types of relationships, not just many-to-many relationships. For general information about relationships, see section 10.3.7 of the Enterprise JavaBeans Specification, v2.1.

Supported Data Types for Mapping

CMP supports a set of JDBC data types that are used in mapping Java data fields to SQL types. Supported JDBC data types are as follows:

BIGINT

BIT

BLOB

CHAR

CLOB

DATE

DECIMAL

DOUBLE

FLOAT

INTEGER

LONGVARBINARY

LONGVARCHAR

NUMERIC

REAL

SMALLINT

TIME

TIMESTAMP

TINYINT

VARCHAR

 

The following table contains the mappings of Java types to JDBC types when automatic mapping is used.

Table 8-4  Java Type to JDBC Type Mappings 

Java Type

JDBC Type

Nullability

boolean

BIT

No

java.lang.Boolean

BIT

Yes

byte

TINYINT

No

java.lang.Byte

TINYINT

Yes

double

DOUBLE

No

java.lang.Double

DOUBLE

Yes

float

REAL

No

java.lang.Float

REAL

Yes

int

INTEGER

No

java.lang.Integer

INTEGER

Yes

long

BIGINT

No

java.lang.Long

BIGINT

Yes

short

SMALLINT

No

java.lang.Short

SMALLINT

Yes

java.math.BigDecimal

DECIMAL

Yes

java.math.BigInteger

DECIMAL

Yes

char

CHAR

No

java.lang.Character

CHAR

Yes

java.lang.String

VARCHAR or CLOB

Yes

Serializable

BLOB

Yes

byte[]

BLOB

Yes

java.util.Date

DATE (Oracle only)

TIMESTAMP (all other databases)

Yes

java.sql.Date

DATE

Yes

java.sql.Time

TIME

Yes

java.sql.Timestamp

TIMESTAMP

Yes


Note

Java types assigned to CMP fields must be restricted to Java primitive types, Java Serializable types, java.util.Date, java.sql.Date, java.sql.Time, or java.sql.Timestamp. An entity bean local interface type (or a collection of such) can be the type of a CMR field.


The following table contains the mappings of JDBC types to database vendor-specific types when automatic mapping is used. For more information about the JDBC driver and database combinations that are supported for Sun Java System Application Server, see “Configurations for Specific JDBC Drivers” on page 324.

Table 8-5  Mappings of JDBC Types to Database Vendor Specific Types 

JDBC Type

PointBase

Oracle

DB2

Sybase ASE 12.5

MS-SQL Server

BIT

BOOLEAN

SMALLINT

SMALLINT

TINYINT

BIT

TINYINT

SMALLINT

SMALLINT

SMALLINT

TINYINT

TINYINT

SMALLINT

SMALLINT

SMALLINT

SMALLINT

SMALLINT

SMALLINT

INTEGER

INTEGER

INTEGER

INTEGER

INTEGER

INTEGER

BIGINT

BIGINT

NUMBER

BIGINT

NUMERIC

NUMERIC

REAL

FLOAT

REAL

FLOAT

FLOAT

REAL

DOUBLE

DOUBLE PRECISION

DOUBLE PRECISION

DOUBLE

DOUBLE PRECISION

FLOAT

DECIMAL(p,s)

DECIMAL(p,s)

NUMBER(p,s)

DECIMAL(p,s)

DECIMAL(p,s)

DECIMAL(p,s)

VARCHAR

VARCHAR

VARCHAR2

VARCHAR

VARCHAR

VARCHAR

DATE

DATE

DATE

DATE

DATETIME

DATETIME

TIME

TIME

DATE

TIME

DATETIME

DATETIME

TIMESTAMP

TIMESTAMP

TIMESTAMP(9)

TIMESTAMP

DATETIME

DATETIME

BLOB

BLOB

BLOB

BLOB

IMAGE

IMAGE

CLOB

CLOB

CLOB

CLOB

TEXT

NTEXT

Automatic Primary Key Generation

The Sun Java System Application Server supports automatic primary key generation for EJB 1.1, 2.0, and 2.1 CMP beans. To specify automatic primary key generation, give the prim-key-class element in the ejb-jar-xml file the value java.lang.Object. CMP beans with automatically generated primary keys can participate in relationships with other CMP beans. The Sun Java System Application Server does not support database-generated primary key values.

If the database schema is created during deployment, the Sun Java System Application Server creates the schema with the primary key column, then generates unique values for the primary key column at runtime.

If the database schema is not created during deployment, the primary key column in the mapped table must be of type NUMERIC with a precision of 19 or more, and must not be mapped to any CMP field. The Sun Java System Application Server generates unique values for the primary key column at runtime.

Fixed Length CHAR Primary Keys

If an existing database table has a primary key column in which the values vary in length, but the type is CHAR instead of VARCHAR, the Sun Java System Application Server automatically trims any extra spaces when retrieving primary key values. It is not a good practice to use a fixed length CHAR column as a primary key. Use this feature with schemas that cannot be changed, such as a schema inherited from a legacy application.

BLOB Support

Binary Large Object (BLOB) is a data type used to store values that do not correspond to other types such as numbers, strings, or dates. Java fields whose types implement java.io.Serializable or are represented as byte[] can be stored as BLOBs.

If a CMP field is defined as Serializable, it is serialized into a byte[] before being stored in the database. Similarly, the value fetched from the database is deserialized. However, if a CMP field is defined as byte[], it is stored directly instead of being serialized and deserialized when stored and fetched, respectively.

To enable BLOB support in the Sun Java System Application Server environment, define a CMP field of type byte[] or a user-defined type that implements the java.io.Serializable interface. If you map the CMP bean to an existing database schema, map the field to a column of type BLOB.

To use BLOB or CLOB datatypes with the Oracle Inet driver for CMP, you must set a special property. For details, see “Inet Oraxo JDBC Driver for Oracle 8.1.7 and 9.x Databases” on page 329.

For automatic mapping, you might need to change the default BLOB column length for the generated schema using the schema-generator-properties element in sun-ejb-jar.xml. See your database vendor documentation to determine whether you need to specify the length. For example:

<schema-generator-properties>
  <property>
    <name>Employee.voiceGreeting.jdbc-type</name>
    <value>BLOB</value>
  </property>
  <property>
    <name>Employee.voiceGreeting.jdbc-maximum-length</name>
    <value>10240</value>
  </property>
  ...
</schema-generator-properties>

CLOB Support

Character Large Object (CLOB) is a data type used to store and retrieve very long text fields. CLOBs translate into long strings.

To enable CLOB support in the Sun Java System Application Server environment, define a CMP field of type java.lang.String. If you map the CMP bean to an existing database schema, map the field to a column of type CLOB.

To use BLOB or CLOB datatypes with the Oracle Inet driver for CMP, you must set a special property. For details, see “Inet Oraxo JDBC Driver for Oracle 8.1.7 and 9.x Databases” on page 329.

For automatic mapping, you might need to change the default CLOB column length for the generated schema using the schema-generator-properties element in sun-ejb-jar.xml. See your database vendor documentation to determine whether you need to specify the length. For example:

<schema-generator-properties>
  <property>
    <name>Employee.resume.jdbc-type</name>
    <value>CLOB</value>
  </property>
  <property>
    <name>Employee.resume.jdbc-maximum-length</name>
    <value>10240</value>
  </property>
  ...
</schema-generator-properties>


Performance-Related Features

The Sun Java System Application Server provides the following features to enhance performance or allow more fine-grained data checking. These features are supported only for entity beans with container managed persistence.

Version Column Consistency Checking

The version consistency feature saves the bean state at first transactional access and caches it between transactions. The state is copied from the cache instead of being read from the database. The bean state is verified by primary key and version column values at flush for custom queries (for dirty instances only) and at commit (for clean and dirty instances).

To use version consistency:

Relationship Prefetching

In many cases when an entity bean’s state is fetched from the database, its relationship fields are always accessed in the same transaction. Relationship prefetching saves database round trips by fetching data for an entity bean and those beans referenced by its CMR fields in a single database round trip.

To enable relationship prefetching for a CMR field, use the default subelement of the fetched-with element in the sun-cmp-mappings.xml file. By default, these CMR fields are prefetched whenever findByPrimaryKey or a custom finder is executed for the field, or when the field is navigated to from a relationship. (Recursive prefetching is not supported, because it does not usually enhance performance.) To disable prefetching for specific custom finders, use the prefetch-disabled element in the sun-ejb-jar.xml file.

Read-Only Beans

Another feature that the Sun Java System Application Server provides is the read-only bean, an entity bean that is never modified by an EJB client. Read-only beans avoid database updates completely. A read-only bean is not portable.

A read-only bean can be used to cache a database entry that is frequently accessed but rarely updated (externally by other beans). When the data that is cached by a read-only bean is updated by another bean, the read-only bean can be notified to refresh its cached data.

The Sun Java System Application Server provides a number of ways by which a read-only bean’s state can be refreshed. By setting the refresh-period-in-seconds element in the sun-ejb-jar.xml file and the trans-attribute element in the ejb-jar.xml file, it is easy to configure a read-only bean that is (a) always refreshed, (b) periodically refreshed, (c) never refreshed, or (d) programmatically refreshed.

Read-only beans are best suited for situations where the underlying data never changes, or changes infrequently. For further information and usage guidelines, see “Using Read-Only Beans” on page 265.


Configuring the Persistence Manager

The resource manager used by the CMP implementation is PersistenceManagerFactory.

An EJB module that contains CMP beans requires the JNDI name of a Persistence Manager resource or JDBC resource in the jndi-name subelement of the cmp-resource element in the sun-ejb-jar.xml file. If the JNDI name refers to a JDBC Resource, set PersistenceManagerFactory properties as properties of the cmp-resource element in the sun-ejb-jar.xml file.

In the Administration Console, open the Resources component, then select Persistence Managers or JDBC. Refer to the Sun Java System Application Server Administration Guide for information on creating a new persistence manager.

For a list of JDBC driver and database combinations that are supported for Sun Java System Application Server, see “Configurations for Specific JDBC Drivers” on page 324. For an up to date list of the JDBC drivers supported by the Sun Java System Application Server, see the Sun Java System Application Server Release Notes.

For example, if the JDBC resource has the JNDI name jdbc/pmf, set the CMP resource in the sun-ejb-jar.xml file as follows:

<cmp-resource>
  <jndi-name>jdbc/pmf</jndi-name>
</cmp-resource>

For another example, if the Persistence Manager has the JNDI name jdo/pmf, set the CMP resource in the sun-ejb-jar.xml file as follows:

<cmp-resource>
  <jndi-name>jdo/pmf</jndi-name>
</cmp-resource>


Configuring Queries for 1.1 Finders

This section contains the following topics:

About JDOQL Queries

The Enterprise JavaBeans Specification, v1.1 spec does not specify the format of the finder method description. The Sun Java System Application Server uses an extension of Java Data Objects Query Language (JDOQL) queries to implement finder and selector methods. (For EJB 2.0 and later, the container automatically maps an EJB QL query to JDOQL.) You can specify the following elements of the underlying JDOQL query:

The Sun Java System Application Server-specific deployment descriptor (sun-ejb-jar.xml) provides the following elements to store the EJB 1.1 finder method settings:

The bean developer uses these elements to construct a query. When the finder method that uses these elements executes, the values of these elements are used to execute a query in the database. The objects from the JDOQL query result set are converted into primary key instances to be returned by the EJB 1.1 ejbFind method.

The JDO specification (see JSR 12) provides a comprehensive description of JDOQL. The following information summarizes the elements used to define EJB 1.1 finders.

Query Filter Expression

The filter expression is a String containing a boolean expression evaluated for each instance of the candidate class. If the filter is not specified, it defaults to true. Rules for constructing valid expressions follow the Java language, with the following differences:

The following expressions are supported:

Query Parameters

The parameter declaration is a String containing one or more parameter type declarations separated by commas. This follows the Java syntax for method signatures.

Query Variables

The type declarations follow the Java syntax for local variable declarations.

JDOQL Examples

This section provides a few query examples.

Example1

The following query returns all players called Michael. It defines a filter that compares the name field with a string literal:

name == "Michael"

The finder element of the sun-ejb-jar.xml file looks like this:

<finder>
  <method-name>findPlayerByName</method-name>
  <query-filter>name == "Michael"</query-filter>
</finder>

Example 2

This query returns all products in a specified price range. It defines two query parameters which are the lower and upper bound for the price: double low, double high. The filter compares the query parameters with the price field:

low < price && price < high

Query ordering is set to price ascending.

The finder element of the sun-ejb-jar.xml file looks like this:

<finder>
  <method-name>findInRange</method-name>
  <query-params>double low, double high</query-params>
  <query-filter>low &lt; price &amp;&amp; price &lt high</query-filter>
  <query-ordering>price ascending</query-ordering>
</finder>

Example 3

This query returns all players having a higher salary than the player with the specified name. It defines a query parameter for the name java.lang.String name. Furthermore, it defines a variable to which the player’s salary is compared. It has the type of the persistence capable class that corresponds to the bean:

  mypackage.PlayerEJB_170160966_JDOState player

The filter compares the salary of the current player denoted by the this keyword with the salary of the player with the specified name:

  (this.salary > player.salary) && (player.name == name)

The finder element of the sun-ejb-jar.xml file looks like this:

<finder>
  <method-name>findByHigherSalary</method-name>
  <query-params>java.lang.String name</query-params>
  <query-filter>
    (this.salary &gt; player.salary) &amp;&amp; (player.name == name)
  </query-filter>
  <query-variables>mypackage.PlayerEJB_170160966_JDOState player</query-variables>
</finder>


Restrictions and Optimizations

This section discusses restrictions and performance optimizations that pertain to using CMP entity beans.

Eager Loading of Field State

By default, the EJB container loads the state for all CMP fields (excluding relationship, BLOB, and CLOB fields) before invoking the ejbLoad method of the abstract bean. This approach might not be optimal for entity objects with large state if most business methods require access to only parts of the state. If this is an issue, use the fetched-with element in sun-cmp-mappings.xml for fields that are used infrequently.

Restrictions on Remote Interfaces

The following restrictions apply to the remote interface of an entity bean that uses CMP:

Dependent value classes can be exposed in the remote interface or remote home interface, and can be included in the client EJB JAR file.

Sybase Finder Limitation

If a finder method with an input greater than 255 characters is executed and the primary key column is mapped to a VARCHAR column, Sybase attempts to convert type VARCHAR to type TEXT and generates the following error:

com.sybase.jdbc2.jdbc.SybSQLException: Implicit conversion from datatype 'TEXT' to 'VARCHAR' is not allowed. Use the CONVERT function to run this query.

To avoid this error, make sure the finder method input is less than 255 characters.

Date and Time Fields as CMP Field Types

If a CMP field type is a Java date or time type (java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp), make sure that the field value exactly matches the value in the database.

For example, the following code uses a java.sql.Date type as a primary key field:

java.sql.Date myDate = new java.sql.Date(System.currentTimeMillis())
beanHome.create(myDate, ...);

For some databases, this code results in only the year, month, and date portion of the field value being stored in the database. Later on if the client tries to find this bean by primary key as follows:

myBean = beanHome.findByPrimaryKey(myDate);

the bean is not found in the database because the value does not match the one that is stored in the database.

Similar problems can happen if the database truncates the timestamp value while storing it, or if a custom query has a date or time value comparison in its WHERE clause.

For automatic mapping to an Oracle database, fields of type java.util.Date, java.sql.Date, and java.sql.Time are mapped to Oracle’s DATE data type. Fields of type java.sql.Timestamp are mapped to Oracle’s TIMESTAMP(9) data type.

No Support for lock-when-loaded on Sybase and DB2

The lock-when-loaded consistency level is implemented by placing update locks on the data corresponding to a bean when the data is loaded from the database. There is no suitable mechanism available on Sybase and DB2 databases to implement this feature. Therefore, the lock-when-loaded consistency level is not supported on Sybase and DB2 databases.



Previous      Contents      Index      Next     


Part No: 819-0079.   Copyright 2004 Sun Microsystems, Inc. All rights reserved.