Chapter 25 Managing Persistent Component State
When using automatic persistence, EAServer manages all interaction with the remote database.
There are two options for database storage when using automatic persistence:
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:
public abstract String getFirstName(); public abstract void setFirstName(String value);
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.
Configuring automatic persistence
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".
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.
Display the Component Properties window in Jaguar Manager and configure the following fields on the Persistence/General subtab:
Use of prepared statements
To support EJB CMP or automatic persistence for entity components,
EAServer uses JDBC prepared statements to execute database queries.
On some databases, the use of prepared statements may exhaust database
resources such as cursors in Oracle. If you encounter this problem,
edit the database type properties file in the EAServer Repository/DatabaseType subdirectory.
Look for a line that contains "statementCache" and edit
the setting to look like this:
com.sybase.jaguar.databasetype.statementCache=falseIf the
statementCache
setting
is not present, add the line above to the file.
map:table
WARNING! | Carefully evaluate your concurrency control model before deploying your application. Concurrency control greatly affects performance as well as the integrity of your back-end database. See "Configure concurrency control" for more information. |
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".
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; }
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:
Configuring key generation to use the Sybase identity
datatype
com.sybase.jaguar.component.generateKey
property
to true
. The default is false
.
com.sybase.jaguar.component.db.sequence
is
not set, or set to no value.
Configuring key generation using the Oracle sequence
datatype
com.sybase.jaguar.component.generateKey
property
to true
. The default is false
.
com.sybase.jaguar.component.db.sequence
.
This property specifies the name of the Oracle sequence to use.
The default is:
table_keys
Configuring key generation
to use a key lookup table
com.sybase.jaguar.component.generateKey
property
to true
. The default is false
.
com.sybase.jaguar.component.db.sequence
to
a value:
table += key_use_rate
_keys
;
for example, if the main table is phone, the
key lookup table is phone_keys.
Overriding the use of native identity types
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.
The entity component's database table must be specified on the Table Name setting in the Persistence/General subtab.
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.
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.
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:
Configuring timestamps for optimistic concurrency
control
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:
|
(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". |
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).
Configuring pessimistic
concurrency control
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.
Refreshing the field-mapping properties
If you do not see mappings for all fields:
The mapping for each field has the form:
column[typespec]
Where:
custinfo.address
specifies
the address column in the custinfo table.
string(255) not nullor:
binary(255) null
binary(255)
maps
to varbinary(255)
for the database
type Sybase_ASE, and to raw(255)
for
Oracle8i. Similarly, string(length)
maps
to the appropriate type to define variable or fixed-length character
columns of the specified length.
binary(length) fixed length null binary(length) fixed length not null string(length) fixed length string(length) fixed length not null
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:
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.
Configuring queries for methods
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]
schema:name=package/component
[default]
if
EJB-QL is not used and EAServer can correctly infer the query.
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.
![]() |
@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". |
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.
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:
@fieldName
to
specify the value of field fieldName.
@fieldName.subfield
to
specify the value of subfield subField where fieldName is
a container-managed field that takes structured types.
For example, you might use this query for a findByPrimaryKey method:
select @firstName, @lastName, @ts from {call sp_select_CustomerProcs @primaryKey}
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.
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.
For update operations Specify the stored procedure call in the form:
{call update-proc param-list}
Where:
com.sybase.jaguar.databasetype.jdbc.proc.executeUpdate
property
is set to true in the database type property file. If a timestamp column
is used for concurrency control, the new timestamp value must be
returned as a column in a single-row result set. If both a row count
and a timestamp are returned, the row count must be first.
@fieldName
to
specify the value of field fieldName.
@fieldName.subfield
to
specify the value of subfield subField where fieldName is
a container-managed field that takes structured types.
@old.fieldName
or @new.fieldName
to
specify the old (last read) or new (updated) value for field fieldName. If
no old
or new
prefix
is used, the new value is assumed. The old
and new
prefixes
cannot be applied to primary key fields, because an instance is
not allowed to change the primary key.
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:
old
and new
prefixes
are not supported.
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:
old
and new
prefixes
are not supported. The stored procedure does not need to return
the key value.
old
and new
prefixes
are not supported.
For example:
select @firstName, @lastName, @ts from {call sp_select_CustomerProcs @primaryKey}
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.
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.
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.
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.
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.
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.
Property | Specifies |
---|---|
Type | The cardinality of the relationship.
Allowable values are:
|
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. |
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. |
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
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. |
![]() |