Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Developer's Guide

- Previous: Chapter 6 Using Enterprise JavaBeans Technology
- Next: Chapter 8 Developing Java Clients

# Chapter 7 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:

- Sun Java System Application Server Support

- Container-Managed Persistence Mapping

- Automatic Schema Generation

- Schema Capture

- Configuring the CMP Resource

- Configuring Queries for 1.1 Finders

- Performance-Related Features

- Restrictions and Optimizations

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

Application Server support for CMP includes:

- Full support for the J2EE v 1.4 specification’s CMP model.

  - Support for commit options B and C for transactions, as defined in the Enterprise JavaBeans Specification, v2.1. See Commit Options.

  - The primary key class must be a subclass of `java.lang.Object`. This ensures portability, and is noted because some vendors allow primitive types (such as `int`) to be used as the primary key class.

- The Application Server CMP implementation, which provides:

  - An Object/Relational (O/R) mapping tool that creates XML deployment descriptors for EJB JAR files that contain beans that use CMP

  - Support for compound (multi-column) primary keys

  - Support for sophisticated custom finder methods

  - Standards-based query language (EJB QL)

  - CMP runtime support. See Configuring the CMP Resource.

- Application Server performance-related features, including:

  - Version column consistency checking

  - Relationship prefetching

  - Read-Only Beans

  For details, see Performance-Related Features.

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

- Mapping Capabilities

- The Mapping Deployment Descriptor File

- Mapping Considerations

## 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 Application Server include:

- Mapping a CMP bean to one or more tables

- Mapping CMP fields to one or more columns

- Mapping CMP fields to different column types

- Mapping tables with compound primary keys

- Mapping tables with unknown primary keys

- Mapping CMP relationships to foreign keys

- Mapping tables with overlapping primary and foreign keys

## The Mapping Deployment Descriptor File

Each module with CMP beans must have the following files:

- `ejb-jar.xml`: The J2EE standard file for assembling enterprise beans. For a detailed description, see the Enterprise JavaBeans Specification, v2.1.

- `sun-ejb-jar.xml`: The Application Server standard file for assembling enterprise beans. For a detailed description, see The sun-ejb-jar.xml File.

- `sun-cmp-mappings.xml`: The mapping deployment descriptor file, which describes the mapping of CMP beans to tables in a database. For a detailed description, see The sun-cmp-mappings.xml File.

The `sun-cmp-mappings.xml` file can be automatically generated and does not have to exist prior to deployment. For details, see Generation Options.

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 can be case-sensitive. Make sure that the table names in the `sun-cmp-mappings.xml` file match the names in the database.

Relationships should always be mapped to the primary key field(s) of the related table.

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 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 “Create Database Mapping” topic in the deploytool’s online help.

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.

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

## Mapping Considerations

This section addresses the following topics:

- Join Tables and Relationships

- Automatic Primary Key Generation

- Fixed Length CHAR Primary Keys

- Managed Fields

- BLOB Support

- CLOB Support

The data types used in automatic schema generation are also suggested for manual mapping. These data types are described in Supported Data Types.

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

### Automatic Primary Key Generation

The 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 Application Server does not support database-generated primary key values.

If the database schema is created during deployment, the 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 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 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.

### Managed Fields

A managed field is a CMP or CMR field that is mapped to the same database column as another CMP or CMR field. CMP fields mapped to the same column and CMR fields mapped to exactly the same column lists always have the same value in memory. For CMR fields that share only a subset of their mapped columns, changes to the columns affect the relationship fields in memory differently. Basically, the Application Server always tries to keep the state of the objects in memory synchronized with the database.

A managed field can have any fetched-with subelement except `<default/>`.

### 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 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 data types larger than 4 KB for CMP using the Inet Oraxo JDBC Driver for Oracle 8.1.7 and 9.x Databases, you must set the `streamstolob` property value to `true`.

For a list of the JDBC drivers currently supported by the Application Server, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Release Notes. For configurations of supported and other drivers, see Configurations for Specific JDBC Drivers.

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 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 data types larger than 4 KB for CMP using the Inet Oraxo JDBC Driver for Oracle 8.1.7 and 9.x Databases, you must set the `streamstolob` property value to `true`.

For a list of the JDBC drivers currently supported by the Application Server, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Release Notes. For configurations of supported and other drivers, see Configurations for Specific JDBC Drivers.

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>

# Automatic Schema Generation

The automatic schema generation feature provided in the Application Server defines database tables based on the fields in entity beans and the relationships between the fields. This insulates developers from many of the database related aspects of development, allowing them to focus on entity bean development. The resulting schema is usable as-is or can be given to a database administrator for tuning with respect to performance, security, and so on.

This section addresses the following topics:

- Supported Data Types

- Generation Options

## Supported Data Types

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, 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 7–1 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 a list of the JDBC drivers currently supported by the Application Server, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Release Notes. For configurations of supported and other drivers, see Configurations for Specific JDBC Drivers.

Table 7–2 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`

## Generation Options

Deployment descriptor elements or `asadmin` command line options can control automatic schema generation by:

- Creating tables during deployment

- Dropping tables during undeployment

- Dropping and creating tables during redeployment

- Specifying the database vendor

- Specifying that table names are unique

- Specifying type mappings for individual CMP fields

Note –

Before using these options, make sure you have a properly configured CMP resource. See Configuring the CMP Resource.

You can also use the deploytool to perform automatic mapping. For more information about using the deploytool, see the “Create Database Mapping” topic in the deploytool’s online help.

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.

Automatic schema generation is not supported for beans with version column consistency checking. Instead, work with your database administrator to create the schema and add the required triggers. See Version Column Consistency Checking.

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 cmp-resource and Configuring the CMP Resource.

Table 7–3 `sun-ejb-jar.xml` Generation 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 column attributes in `property` subelements. Each property name is of the following format: bean-name`.`field-name`.`attribute For example:
    Employee.firstName.jdbc-type
Column attributes are described in Table A–98. 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 further information and an example, see schema-generator-properties.

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

Table 7–4 `asadmin deploy` and `asadmin deploydir` Generation 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 7–5 `asadmin undeploy` Generation 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 Enterprise Edition 8.1 2005Q2 Reference Manual.

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

# Schema Capture

This section addresses the following topics:

- Automatic Database Schema Capture

- Using the capture-schema Utility

## Automatic Database Schema Capture

You can configure a CMP bean in 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.

Note –

Before capturing the database schema automatically, make sure you have a properly configured CMP resource. See Configuring the CMP Resource.

## Using the capture-schema Utility

You can use the `capture-schema` command to manually generate the database metadata (`.dbschema`) file. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Reference Manual.

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

Keep the following in mind when using the `capture-schema` command:

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

- If more than one schema is accessible for the schema user, more than one table with the same name might be captured if the `-schemaname` parameter of `capture-schema` is not set.

- The schema name must be upper case.

- Table names in databases are case-sensitive. Make sure that the table name matches the name in the database.

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

# Configuring the CMP Resource

An EJB module that contains CMP beans requires the JNDI name of a JDBC resource or Persistence Manager 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 JDBC or Persistence Managers. Refer to the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide for information on creating a new CMP resource.

For a list of the JDBC drivers currently supported by the Application Server, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Release Notes. For configurations of supported and other drivers, see Configurations for Specific JDBC Drivers.

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

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

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

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

# Configuring Queries for 1.1 Finders

This section contains the following topics:

- About JDOQL Queries

- Query Filter Expression

- Query Parameters

- Query Variables

- JDOQL Examples

## About JDOQL Queries

The Enterprise JavaBeans Specification, v1.1 spec does not specify the format of the finder method description. The 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:

- Filter expression - A Java-like expression that specifies a condition that each object returned by the query must satisfy. Corresponds to the WHERE clause in EJB QL.

- Query parameter declaration - Specifies the name and the type of one or more query input parameters. Follows the syntax for formal parameters in the Java language.

- Query variable declaration - Specifies the name and type of one or more query variables. Follows the syntax for local variables in the Java language. A query filter might use query variables to implement joins.

- Query ordering declaration - Specifies the ordering expression of the query. Corresponds to the ORDER BY clause of EJB QL.

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

`query-filterquery-paramsquery-variablesquery-ordering`

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:

- Equality and ordering comparisons between primitives and instances of wrapper classes are valid.

- Equality and ordering comparisons of Date fields and Date parameters are valid.

- Equality and ordering comparisons of String fields and String parameters are valid.

- White space (non-printing characters space, tab, carriage return, and line feed) is a separator and is otherwise ignored.

- The following assignment operators are not supported:

  - =, +=, etc.

  - pre- and post-increment

  - pre- and post-decrement

- Methods, including object construction, are not supported, except for:

      Collection.contains(Object o)
      Collection.isEmpty()
      String.startsWith(String s)
      String.endsWith(String e)

  In addition, the Application Server supports the following nonstandard JDOQL methods:

      String.like(String pattern)
      String.like(String pattern, char escape)
      String.substring(int start, int length)
      String.indexOf(String str)
      String.indexOf(String str, int start)
      String.length()
      Math.abs(numeric n)
      Math.sqrt(double d)

- Navigation through a null-valued field, which throws a `NullPointerException`, is treated as if the sub-expression returned `false`.

Note –

Comparisons between floating point values are by nature inexact. Therefore, equality comparisons (== and !=) with floating point values should be used with caution. Identifiers in the expression are considered to be in the name space of the candidate class, with the addition of declared parameters and variables. As in the Java language, `this` is a reserved word, and refers to the current instance being evaluated.

The following expressions are supported:

- Operators applied to all types where they are defined in the Java language:

  - relational operators (==, !=, >, <, >=, <=)

  - boolean operators (&, &&, |, ||, ~, !)

  - arithmetic operators (+, -, *, /)

  String concatenation is supported only for String + String.

- Parentheses to explicitly mark operator precedence

- Cast operator

- Promotion of numeric operands for comparisons and arithmetic operations. The rules for promotion follow the Java rules (see the numeric promotions of the Java language specification) extended by BigDecimal, BigInteger, and numeric wrapper classes.

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

### Example 1

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>

# Performance-Related Features

The 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

- Relationship Prefetching

- Read-Only Beans

Note –

Use of any of these features results in a non-portable application.

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

1. Create the version column in the primary table.

2. Give the version column a numeric data type.

3. Provide appropriate update triggers on the version column.

   These triggers must increment the version column on each update of the specified row.

4. Specify the version column.

   This is specified in the check-version-of-accessed-instances subelement of the consistency element in the `sun-cmp-mappings.xml` file.

5. Map the CMP bean to an existing schema.

   Automatic schema generation is not supported for beans with version column consistency checking. Instead, work with your database administrator to create the schema and add the required triggers.

## 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 entity, or when the entity 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 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 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 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.

# Restrictions and Optimizations

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

- Eager Loading of Field State

- Restrictions on Remote Interfaces

- Sybase Finder Limitation

- Date and Time Fields as CMP Field Types

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

- Set RECURSIVE_TRIGGERS to false on MSSQL

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

- Do not expose the `get` and `set` methods for CMR fields or the persistence collection classes that are used in container-managed relationships through the remote interface of the bean.

  However, you are free to expose the `get` and `set` methods that correspond to the CMP fields of the entity bean through the bean’s remote interface.

- Do not expose the container-managed collection classes that are used for relationships through the remote interface of the bean.

- Do not expose local interface types or local home interface types through the remote interface or remote home interface of the bean.

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.

## Set RECURSIVE_TRIGGERS to false on MSSQL

For version consistency triggers on MSSQL, the property `RECURSIVE_TRIGGERS` must be set to `false`, which is the default. If set to `true`, triggers throw a `java.sql.SQLException`.

Set this property as follows:

    EXEC sp_dboption 'database-name', 'recursive triggers', 'FALSE'
    go

You can test this property as follows:

    SELECT DATABASEPROPERTYEX('database-name', 'IsRecursiveTriggersEnabled')
    go

- Previous: Chapter 6 Using Enterprise JavaBeans Technology
- Next: Chapter 8 Developing Java Clients

- © 2010, Oracle Corporation and/or its affiliates