Chapter 25 Managing Persistent Component State


Automatic entity persistence

When using automatic persistence, EAServer manages all interaction with the remote database.

How it works

There are two options for database storage when using automatic persistence:

Note   Identifying the storage technique The component uses mapped field storage if the value of the Table field on the Persistence tab begins with map: , for example, map:MyTable .

The automatic persistence architecture includes:

Configuring automatic persistence

If you are developing EJB entity beans, use an EJB development tool to create an EJB-JAR file that defines the components' CMP fields and container-managed relationships. You can define CMP entity beans in Jaguar Manager, but it may be easier with a dedicated EJB development tool.

When you have CMP entity beans defined in an EJB-JAR file, import the EJB-JAR file into Jaguar Manager as described in the EAServer System Administration Guide. The JAR importer configures appropriate defaults for almost all settings. After importing, review the persistence settings described below and verify that they are correct.

To use automatic persistence for non-EJB entity components, you must configure the persistence properties in Jaguar Manager.

Component properties for automatic persistence are configured on the Persistence tab in the Component Properties dialog box. This tab has subtabs to display the categorized properties.

Steps Configuring automatic persistence

  1. Configure CMP version for EJB 2.0 entity beans.
  2. Configure Persistence/General subtab properties.
  3. Enable automatic key generation if your entity component uses a table with an automatically generated key or your EJB entity bean uses java.lang.Object as the primary key class.
  4. Configure database tables.
  5. Configure concurrency control.
  6. Configure field-mapping properties.
  7. Configure finder- and ejbSelect-method queries.
  8. Configure table-mapping properties.
  9. Configure relationship components if using EJB 2.0 container-managed relationships.

After you have verified the deployment is working, you can optimize your component's performance by configuring in-memory caching of instance data and query results. See "Entity object and query caching".


Configure CMP version for EJB 2.0 entity beans

For EJB 2.0 entity beans, choose a CMP version on the General tab in the Component Properties dialog box. Choose 2.0 to match the EJB 2.0 specified behavior. Choose 1.1 to match the EJB 1.1 persistence model. Use 2.0 CMP for new development, and 1.1 for existing beans that have code that requires the 1.1 model.

For EJB 1.1 entity beans, you can not set the CMP version.

Configure Persistence/General subtab properties

Display the Component Properties window in Jaguar Manager and configure the following fields on the Persistence/General subtab:

Defining the state datatype

For automatic persistence, you must define a state datatype to be used for exchange of data between the component's skeleton and the storage component.

State types for mapped fields If using the mapped-fields storage model, the state datatype must be an IDL structure. Enter the structure name in the in the State field on the Persistence/General subtab in the Component Properties Dialog box. For example:

MyPackage::CustomerState

You can enter the name of an IDL structure that does not exist; Jaguar Manager creates it when you click Ok in the Component Properties dialog box. Afterwards, navigate to the IDL definition and edit the structure as described in "Editing IDL types, exceptions, and interfaces".

Define the structure field names and types as follows:

State types for binary storage If you are using the binary storage model, enter the name of an IDL structure or serializable Java class. Your state accessor methods must contain code to get and set this data to and from the current instance, as described in "Defining the state methods".

Defining the state methods

For automatic persistence in non-EJB components or in EJB components using the binary-storage persistence model, your component implementation must contain state accessor methods to read state data from the current instance and apply state data to the current instance. Specify the names of these methods on the State Methods field in the Persistence/General subtab. If you specify no value, the default is getState,setState .

Your component implementation must contain these methods, but they should not be listed in the component's client interfaces. The getState method returns an instance of the type specified by the State field, and the setState method accepts a parameter of this type. For example, if the State type is ShoppingCartState, the getState and setState methods might be defined as follows in Java:

private ShoppingCartState data;

ShoppingCartState getState()
{
    return data;
}

void setState(ShoppingCartState state)
{
    data = state;
}

Enable automatic key generation

If automatic key generation is enabled, keys are created automatically for every row inserted in the table. An EJB 2.0 entity bean that uses CMP and specifies java.lang.Object as the primary key class requires automatic key generation. Components of other types can use this feature as well.

If you are mapping container-managed fields to multiple tables, automatic key generation applies only to the main table, specified on the Persistence/General subtab.

EAServer supports three mechanisms for key generation:

Steps Configuring key generation to use the Sybase identity datatype

  1. On the Persistence/General subtab, set the Primary Key to the IDL type XDT::Integer.
  2. Use the All Properties tab to set the com.sybase.jaguar.component.generateKey property to true . The default is false .
  3. In the Persistence/Field Mappings tab, verify that the key field is mapped to the Sybase identity type or a compatible type.
  4. Use the All Properties tab to verify that the property com.sybase.jaguar.component.db.sequence is not set, or set to no value.

Steps Configuring key generation using the Oracle sequence datatype

  1. On the Persistence/General subtab, set the Primary Key to the IDL type XDT::Integer.
  2. Use the All Properties tab to set the com.sybase.jaguar.component.generateKey property to true . The default is false .
  3. In the Persistence/Field Mappings tab, verify that the key field is mapped to the Oracle sequence type or a compatible type.
  4. If using an existing table or a table that you create yourself (rather than relying on autocreation by EAServer), use the All Properties tab to set the component property com.sybase.jaguar.component.db.sequence . This property specifies the name of the Oracle sequence to use. The default is:
    table_keys
    


    Where table is the main table name specified on the Persistence/General subtab.

Steps Configuring key generation to use a key lookup table

  1. On the Persistence/General subtab, set the Primary Key to the IDL type XDT::Integer.
  2. Use the All Properties tab to set the com.sybase.jaguar.component.generateKey property to true . The default is false .
  3. In the Persistence/Field Mappings tab, verify that the key field is mapped to an integer type that is compatible with the type used in the lookup table.
  4. Use the All Properties tab to set the component property com.sybase.jaguar.component.db.sequence to a value:
    table += key_use_rate
    


    Where:

Steps Overriding the use of native identity types

  1. If you are using Sybase or Oracle, you can force the use of a key lookup table rather than the Sybase identity or Oracle sequence datatypes. To do so, set the com.sybase.jaguar.component.db.sequence . property and specify a key use rate as described in "Configuring key generation to use a key lookup table". If the value of this property contains "+=", EAServer uses a key lookup table regardless of the database type.

Configure database tables

The entity component's database table must be specified on the Table Name setting in the Persistence/General subtab.

Tables for binary storage

If you are using binary storage, simply enter the table name. If you have specified a valid database type in the connection cache properties, EAServer creates the table if it does not exist. "Table schema for binary storage" describes the required table schema.

Tables for mapped-fields storage

If you are using mapped-field storage, you can use actual database table names, or logical table names that do not necessarily exist in the database. You can map fields to several tables, in which case the table named on the Persistence/General tab becomes the "main" table.

Table access is configured by the component's table mapping properties. The default mappings require that the tables exist and are accessed by standard SQL commands.

Use logical names if you must use stored procedures for data access, or are using a non-SQL database. You must configure the data access operations for logical tables, as described in "Configure table-mapping properties".

If you have specified a valid database type in the connection cache properties, EAServer creates database tables if they do not exist. Otherwise, you or your database administrator (DBA) must create tables manually. In any case, for deployment to production servers, your DBA may require that tables be created beforehand with an optimized index model.

The table column types must agree with the mapped fields (see "Configure field-mapping properties"), and contain a timestamp column if timestamps are used for concurrency control. "Supported Java, IDL, and JDBC/SQL types" lists the supported JDBC/SQL types and the corresponding Java and IDL field types.

Configure concurrency control

When using mapped fields, you must also choose a concurrency control model. Concurrency control prevents overlapping updates from entity instances running in different threads or different servers, or from applications running outside of EAServer. There are two approaches for concurrency control:

Steps Configuring timestamps for optimistic concurrency control

  1. Configure the Timestamp field on the Persistence/General subtab. Table 25-1 describes the allowable values. For best performance when using tables with many columns or large column values (such as Sybase text or image columns), specify a timestamp column as described in Table 25-1.

    If multiple tables are used and you specify a timestamp column, all tables must contain a column with the same name and datatype.
    Table 25-1: Timestamp field values
    Value Specifies
    A column name The name of a single column in each table that serves as the timestamp to detect update collisions. If the component uses multiple tables, each must contain a timestamp column with this name. The column type can be:
    • A 4-byte integer - this is the default timestamp column type. All processes that update the table(s) must increment the timestamp with each update, or your DBA can create an update trigger to increment the timestamp automatically.
    • The database timestamp type - you can use the timestamp datatype if using Sybase Adaptive Server Enterprise or Adaptive Server Anywhere version 7.0 or later. You must also define a field mapping property to specify the timestamp datatype as described in "Configure field-mapping properties". For example, if the column name is ts, specify the mapping as:
      ts[dbts not null]
      


      dbts is a logical type name mapped to the timestamp type in the Sybase_ASE and Sybase_ASA database types. If the database does not support timestamps, a 4-byte integer counter is used instead.
    (No value) On update, all row values are compared to the last-read values to detect update collisions. Note that this can cause poor performance with tables that have many columns, or large column values such as Sybase text or image columns. Whenever possible, the use of a timestamp column is recommended in these cases.
    "None" Disables optimistic concurrency control. In this case, you are strongly advised to configure locking as described in "Configuring pessimistic concurrency control".
  2. Optionally configure auto-retry for transactions by setting the com.sybase.jaguar.component.tx_retry component property to true. The default is false. Auto-retry is not appropriate for all applications. For example, an end user may want to cancel a purchase if the item price has risen! If auto-retry is disabled, clients must be coded to retry or abort transactions that fail because of stale data. The exception thrown is CORBA::TRANSIENT (for EJB clients, this exception is the root cause of the java.rmi.RemoteException thrown by the EJB stub).
  3. Verify that the Select With Lock option on the Persistence/General subtab is disabled.

Steps Configuring pessimistic concurrency control

  1. To configure pessimistic concurrency control, you can:

Configure field-mapping properties

Field-mapping properties specify which table columns correspond to the component's container-managed fields, the primary key (which may map to one or several columns), and the timestamp (if used for concurrency control). Before configuring field mappings, make sure that:

Configure field-mapping properties in the Component Properties dialog box, on the Persistence/Field Mapping subtab. This subtab displays a mapping for each container-managed field (based on the state datatype structure fields), the key fields, and the timestamp column (if specified). The initial mappings use default values which you may need to adjust.

Note   Refreshing the field-mapping properties If you do not see mappings for all fields:

  1. Verify that the state type, primary key, and timestamp have been configured.
  2. Click Ok in the Component Properties dialog box to save the properties.
  3. Reopen the Component Properties dialog box.

The mapping for each field has the form:

column[typespec]

Where:

Configure finder- and ejbSelect-method queries

Each finder method in the component's home interface requires a database query to select a set of primary keys. For example, the findByPrimaryKey method selects the key that matches the input parameter. A findAll method might return all keys in the table. ejbSelect methods in an EJB 2.0 entity bean also require query mappings.

There are two ways to specify query mappings:

Note   If you have deployed EJB CMP entity beans from an EJB-JAR file If you have deployed EJB CMP entity beans from an EJB-JAR file, the special query mapping value [unknown] indicates that you must specify a query. The special value [default] means that EAServer can infer the query based on the method's name pattern. The special value ejbQuery: indicates the query uses EJB-QL that was specified in the deployment descriptor.

Steps Configuring queries for methods

  1. Display the Persistence/Query Mapping subtab in the Component Properties dialog box. One mapping displays for each finder method in the component's home interface and for each ejbSelect method.
  2. To change the query mapping, highlight the method name or query, then click Modify. Edit the value as follows:
  3. Using EJB-QL: The special EAServer query ejbQuery: indicates that an EJB-QL query is defined for the finder or ejbSelect method. You can add additional parameters to configure caching of the query results, as described in "Enabling query caching", for example:
    ejbQuery:[cache]
    



    If the special mapping ejbQuery: is specified for the method, the EJB-QL query can be specified using a second query mapping for the method. The EJB-QL query must follow the syntax described by the EJB 2.0 specification.

    In EJB-QL, each entity bean is represented by a schema name. EAServer defines the EJB-QL schema names in the properties of the package that contains the component. To map schema names to components in the package, specify a package property of the form:
    schema:name=package/component
    


    Where name is the schema name, package is the EAServer package name and component is the component name. If the package properties do not specify a schema name for the component, the default is the component name. Schemas used in queries for a component can only refer to components in the same EAServer package.
  4. Using EAServer extended SQL: Enter one of the following for the query:

Table 25-2: Finder query placeholders
Placeholder To indicate
[key] The table's primary key (which can consist of multiple columns).
[table] The name of the main table, specified in the Table field on the Persistence/General subtab.
@param Reference the value of parameter param in the finder method's IDL signature.

Note   If the component was imported from an EJB-JAR file, the IDL parameter names do not match the original Java implementation. The IDL parameters are named p0, p1, and so forth.
@param.fieldName If method parameter param is not a simple type, reference the value of field fieldName.
[cache cache-props] When appended to the query, configures query caching. See "Enabling query caching".

Defining select query filters in extended SQL

Use the syntax of these examples if you are using database tables that can be accessed directly with standard SQL select statements.

This query uses the value of the expiryDate parameter to filter a range of closingDate column values. Note the select keyword, column list, and from clause are omitted:

where closingDate < @expiryDate

This query returns all rows in a table and includes a column list and from clause:

select firstname, lastname, [key] from [table]

If you specify a column list and you are using entity object caching, you will get better results if you select all columns, so that the object cache can be populated from the query results. Omit the select keyword, the column list, and the from clause to avoid this complication.

The query must be a complete select statement or omit the select keyword, column list, and from clause.

Calling stored procedures in extended SQL

You can call stored procedures to return the results required to execute a finder or ejbSelect query. To specify a stored procedure call, use the syntax:

select column-list from {call proc param-list}

Where:

For example, you might use this query for a findByPrimaryKey method:

select @firstName, @lastName, @ts from {call sp_select_CustomerProcs @primaryKey}

Configure table-mapping properties

Table mapping allows you to customize the DBMS queries and DML statements used to support ejbCreate/ctsCreate, ejbLoad/ctsLoad, ejbStore/ctsStore and ejbRemove/ctsRemove.

The default table mappings suffice for direct access to tables in standard SQL databases. You can customize the default SQL commands. For example, you might optimize the select query to force the use of an index by adding proprietary DBMS keywords.

You must configure explicit table access commands if you use stored procedures for data access or a non-SQL database.

To configure table mapping for an entity component, display the Persistence/Table Mapping subtab in the Component Properties window. Mapping properties display for the main table, specified on the Persistence/General tab, and any other table referenced in field mapping properties. Each table has mapping properties for the operations listed in Table 25-3.

Table 25-3: Table mapping operation names
Operation Specifies
select The database command for ejbLoad/ctsLoad operations.
update The database command for ejbStore/ctsStore operations.
insert The database command for ejbCreate/ctsCreate operations.
delete The database command for ejbRemove/ctsRemove operations.
notify When you are using object caching and have enabled database change notification, this property specifies the message service topic name used to notify the object cache of table changes. The default is the unqualified table name.

See "Enabling database change notification" for more information on this feature.

For select, update, insert, and delete operations, the mapping can be [default] , to specify that standard SQL commands be used, a stored procedure call, or alternate query text.

Configuring stored procedure invocations

For update operations Specify the stored procedure call in the form:

{call update-proc param-list}

Where:

For example:

{call sp_update_CustomerProcs @primaryKey, @firstName, @lastName, @old.ts}

The update procedure must contain logic to perform concurrency control. If using a timestamp column, make sure the timestamp value is passed to the procedure and used in the update statement. If using OCC with value comparisons, make sure the procedure accepts all old values as well as new values, and contains the value comparison logic.

For delete operations Specify the stored procedure call in the form:

{call delete-proc param-list}

Where:

For example:

{call sp_delete_CustomerProcs @primaryKey}

For insert operations Specify the stored procedure call in the form:

{call insert-proc param-list}

Where:

For example:

{call sp_insert_CustomerProcs @primaryKey, @firstName, @lastName}

For select operations Specify the stored procedure call in the form:

select read-param-list from {call select-proc key-param-list}

Where:

For example:

select @firstName, @lastName, @ts from {call sp_select_CustomerProcs @primaryKey}

Specifying alternate query text

You can enter query text for the insert, delete, update, and select operations, using the same parameter placeholder format as used for stored procedures.

Special syntax is required also for ordinary SQL select statements to specify the mapping of fields to expected result set columns. For example, if storing customer names in a separate table and not using stored procedures, you might specify the select operation as:

select=select @firstName = firstName, @lastName = lastName from TestCMP_Customer where primaryKey = @primaryKey

When this query is issued to the JDBC driver, it will be in the form of a JDBC prepared statement, such as:

select firstName, lastName from TestCMP_Customer where primaryKey = ?

The persistence engine removes the "@field" references from the query, allowing the proprietary syntax of the target DBMS to be used effectively. For example, the query could be modified to force the use of an index by using proprietary DBMS keywords.

Configure relationship components

EAServer uses relationship components to manage relationships between EJB 2.0 CMP entity beans.

EBJ 2.0 CMP entity beans can have container-managed relationships. A relationship allows an entity component to have a container-managed field that contains instances of another (or the same) entity component. For example, an Order component may have an items field that consists of a collection of Inventory objects representing the items being purchased. Or, an Employee component may be related to itself, with manager and employees fields that contain Employee instances.

A relationship can be unidirectional or bidirectional. For example, the Employee-Manager relationship is typically bidirectional: it's convenient to know who works for a particular employee as well as who reports to that employee. An Order-Inventory relationship is typically unidirectional: it would not be practical to track every order that a line item is added to.

The relationship component name contains one or more hyphens. Only relationship components may have names that contain hyphens. Relationship components created by deploying EJB-JAR files have names of the form:

component1-component2

Or:

component-field

Where component1 and component2 are names of two related components. The component-field form is used when a component is related to itself (such as the employee-manager relationship). In this case,. field is the field name used for maintaining one side of the relationship. For example, an Employee component may have a Manager field, resulting in the relationship component Employee-Manager.

Relationship components are supported only for EJB 2.0 CMP entity beans. Relationship components are themselves CMP entity beans, and must have the relationship properties described below. Related components must be in the same EAServer package. The implementation of a relationship component is generated when you generate skeletons for the components in the relationship.

Maintaining the relationship

The tables represented by related components must be related in the database. There are two techniques to maintain the table relationship:

Foreign keys offer the best performance, but can be used only when one destination instance relates to a given source instance. For example, you can use foreign keys to manage the Employee-to-Manager relationship (an employee has one manager), but must use a join table for the Manager-to-Employee relationship (a manager has many employees). In bidirectional relationships, you must configure the technique for each direction of the relationship.

Cascading deletes

In some cases, you may want an ejbRemove operation to delete "through" a relation. For example, an Order instance represents an online purchase, and is related to LineItem instances that represent items included in the order. In this case, removal of an Order instance should remove LineItem instances contained in the order.

You can configure the Cascade Delete properties for each side of a one-to-one relationship, and on the "one" side of many-to-one and one-to-many relationships.

Configuring relationship component properties

To configure relationship properties, display the Component Properties for the relationship component, then display the Persistence/Relationship subtab and configure the Relationship Type settings and Relationship Name settings, described in Table 25-4 and Table 25-5, respectively.

Note   Regenerating the relationship component After editing relationship component properties, regenerate the skeletons for the package and refresh the package to ensure the changes take effect.

Table 25-4: Relationship Type properties
Property Specifies
Type The cardinality of the relationship. Allowable values are:
  • One to One - one from component instance is related to one to instance.
  • One to Many - one from instance is related to many to instances.
  • Many to One - many from instances are related to one to instance.
  • Many to Many - many from instances are related to many to instances.
From Component The name of the from component in the relationship, in the form:
package/component


The from component contains a container-managed field that contains instances of the to component specified by the To Component property.
From Field The name of the container-managed field in the from component that contains related to component instance references.
From Field Type For one-to-many and many-to-many relationships, specifies the Java type used in the getter and setter methods of the from component. Allowable values are Collection and Set.

For single-valued fields, no value is required. You can set this property by setting the from-field-type property on the All Properties tab.
From Query When a join table is used, the name of a query used to select the to component's primary keys that are required to populate the from component field indicated by the From Field setting. This query must be defined by a query mapping property, as described in "Configure finder- and ejbSelect-method queries".
From Role Matches the name of the corresponding ejb-relationship-role element in the EJB-JAR deployment descriptor.
Use Foreign Key Whether to use a join table or foreign keys to maintain the to -from relationship. A value of true indicates that foreign keys must be used.

You can use foreign keys only on the "one" side of a relationship, as described in "Maintaining the relationship".
Cascade Delete Applies only when the relationship-type is one-to-one or one-to-many.

Specifies whether deletion of a an instance on the singleton side of the relation causes deletion of the related instance.
Table 25-5: Relationship Name properties
Property Specifies
Name The name of the relationship. Matches the corresponding ejb-relation-name element in the EJB-JAR deployment descriptor.
To Component The name of the to component in the relationship, in the form:
package/component


For bidirectional relationships, you must also specify values for the To Field, To Field Type, and To Query properties.
To Field The name of the container-managed field in the to component that contains related from component instance references.
To Field Type If a to instance can be related to multiple from instances, specifies the Java type used in the getter and setter methods of the from component. Allowable values are Collection and Set.

For single-valued fields, no value is required. You can set this property by setting the to-field-type property on the All Properties tab.
To Query When a join table is used, the name of a query used to select the from component's primary keys that are required to populate the to component field indicated by the To Field setting. This query must be defined by a query mapping property, as described in "Configure finder- and ejbSelect-method queries".
To Role Matches the name of the corresponding ejb-relationship-role element in the EJB-JAR deployment descriptor.
Use Foreign Key Whether to use a join table or foreign keys to maintain the from -to relationship. Enable the option if foreign keys must be used.

You can use foreign keys only on the "one" side of a relationship, as described in "Maintaining the relationship".
Cascade Delete Applies only when the relationship-type is one-to-one or many-to-one.

Specifies whether deletion of a an instance on the singleton side of the relation causes deletion of the related instance.

Example properties for a many-to-many bidirectional relationship

The components here are TestCMP/Customer and TestCMP/Account:

relationship-type=many-to-many
relationship-name=Customer-Account
relationship-from=TestCMP/Customer
relationship-to=TestCMP/Account
from-field=accounts
from-field-type=Collection
from-foreign-key=true
from-query=findByCustomer
from-role=customer-has-accounts
to-field-type=Collection
to-field=customers
to-foreign-key=true
to-query=findByAccount
to-role=account-has-customers
cascade-delete=false

Example properties for a recursive, bidirectional, many-to-one relationship

The component here, TestCMP/Employee, is related to itself:

relationship-type=many-to-one
relationship-name=Employee-Manager
relationship-from=TestCMP/Employee
relationship-to=TestCMP/Employee
from-field=managerField
from-foreign-key=true
from-query=findByEmployees
from-role=employees-has-manager
to-field=employeesField
to-field-type=Collection
to-foreign-key=true
to-query=findByManager
to-role=manager-has-employees
cascade-delete=false

 


Copyright © 2002 Sybase, Inc. All rights reserved.