# Accelerating Entity Bean Data Access

WebLogic platform provides a number of features to reduce data access latency for CMP entity beans. This topic discusses the following techniques:

- Using Eager Loading in Query Methods
- Using Eager Loading in Relationships
- Query Methods and Modified Data
- Using Read-Only Entity Beans
- Using Optimistic Concurrency
- Using Caching Between Transactions
- Application-Level Caching
- Passing Method Arguments By Reference
- Sorting and Batching Database Operations

Note. This topic is meant to specifically point out a number of Weblogic-specific features that speed up data access. Design patterns, the use of local interfaces, and other J2EE design and architecture issues that affect performance are not addressed here. For more information on those topics, please consult your favorite J2EE documentation.

## Using Eager Loading in Query Methods

A field-group represents a subset of container-managed persistence (cmp) and container-managed relation (cmr) fields of a single entity bean. You can associate a group with a query method (or relationship; see below), so that when a bean is loaded as the result of executing a query, only the fields mentioned in the group are loaded from the database when the query method returns, a concept known as eager loading. An entity bean's field that is not part of that group is not loaded at that point, but will be loaded if you subsequently access this field (through a get method), a concept known as lazy loading. Data access will be improved if you take advantage of eager loading while avoiding lazy loading, that is, by making sure that all and only the fields that you need are returned by the query method.

Note. Eager loading is way of specifying what data are loaded and cached for the duration of a transaction. If a finder method is used in one transaction, and in a subsequent transaction the bean returned by that finder method is accessed (using a get method), the accessed field is loaded anew (as the data might have changed in the meantime). If caching between transactions is enabled, then eager loading will be used the first time to cache the data, but subsequently the cached data is used instead. For more information about caching, see the various caching sections below.

To enable eager loading of field groups, you must do the following:

- Verify that ejbgen:entity finders-load-bean is set to true (or was left unspecified). When set to false, query methods will always just load the primary key values of the beans returned by the query.
- Define your cmp and cmr fields, and group related fields together using the group-names attribute. You can make a field a member of multiple groups if necessary.
- Define your select and/or find method(s), and use the group-name attribute to specifies which field group should be loaded eagerly.

In the following code snippet two field groups are defined, as well as a findAll method that uses eager loading of one of these groups. Particularly relevant lines of code are shown in bold:

    /**
     * @ejbgen:entity prim-key-class="java.lang.Integer"  ...
     *
     * ...
     *
     * @ejbgen:finder group-name="queryGroup"
     * ejb-ql="SELECT OBJECT(o) from CachedOne as o"
     * generate-on="Local"
     * signature="Collection findAll()"
     */
    abstract public class CachedOne extends GenericEntityBean implements EntityBean
    {

        /**
         * @ejbgen:cmp-field group-names="queryGroup" primkey-field="true" column="Index"
         * @ejbgen:local-method
         */
        public abstract Integer getIndex();

        /**
         * @ejbgen:local-method
         */
        public abstract void setIndex(Integer arg);

        /**
         * @ejbgen:cmp-field group-names="queryGroup" column="Name"
         * @ejbgen:local-method
         */
        public abstract String getFieldOne();

        /**
         * @ejbgen:local-method
         */
        public abstract void setFieldOne(String arg);

        /**
         * @ejbgen:cmp-field group-names="nonQueryGroup" column="FieldTwo"
         * @ejbgen:local-method
         */
        public abstract String getFieldTwo();

        /**
         * @ejbgen:local-method
         */
        public abstract void setFieldTwo(String arg);

        ...

## Using Eager Loading in Relationships

If a query method returns (one or) a set of entity bean object(s), the cmp and cmr fields of each object are loaded at this point (subject perhaps to eager loading of field groups, as discussed above). If subsequently a cmr field (relationship field) accessor method is used to, for instance, get a set of related entity beans referenced via the field, those beans are loaded at this point, requiring a separate database read. To reduce the number of database queries and enhance performance, you can enable eager loading of relationships, such that in the results returned by a query method, related entity beans have also been loaded.

Eager loading of relationships is possible for all entity relationships, with the exception of many-to-many relationships. For more information about relationships, see Entity Relationships. It is also possible to nest eager loading of relationships, that is, for the beans that are loaded as part of a relationship, you can in turn load their entity relationships (see below).

Note. Eager loading is way of specifying what data are loaded and cached for the duration of a transaction. If a finder method is used in one transaction, and in a subsequent transaction the bean returned by that finder method is accessed (using a get method), the accessed field is loaded anew (as the data might have changed in the meantime). If caching between transactions is enabled, then eager loading will be used the first time to cache the data, but subsequently the cached data is used instead. For more information about caching, see the various caching sections below.

To enable eager loading of relationships, you must do the following:

- Verify that ejbgen:entity finders-load-bean is set to true (or was left unspecified). When set to false, query methods will always just load the primary key values of the beans returned by the query.
- In the Property Editor, specify the database type to indicate which DBMS is used. Eager loading of relationships uses database-dependent query (outer join) syntax. For more information, see the database-type attribute of @ejbgen:entity Annotation.
- Specify the entity relationship(s) you want to load eagerly. To do so, insert an ejbgen:relationship-caching-element tag and specify the cmr fields that store a reference to the related bean(s). Use the caching-name attribute to name this specification. For more information, see @ejbgen:relationship-caching-element Annotation. If an entity bean has several entity relationships, and different query methods should eagerly load different relationships, you can create multiple eager relationship loading definitions, that is, insert multiple ejbgen:relationship-caching-element tags.
- Define your select and/or find method(s), and use the caching-name attribute to specifies which relationship(s) should be eagerly loaded.

In the following example a findByName method takes a String argument and returns the band(s) matching that name. For the returned band(s), its recordings, represented by RecordingBean instances and referenced through the cmr field recordings, are eagerly loaded at the same time. (The BandBean and RecordingBean are engaged in a one-to-many bidirectional entity relationship.) The code snippet shows the definition of the finder method, the entity relationship, and the eager relationship loading specification:

     * @ejbgen:finder caching-name="LoadRecordings"
     *     ejb-ql="SELECT DISTINCT OBJECT(a) FROM BandEJB AS a WHERE a.name = ?1"
     *     signature="java.util.Collection findByName(java.lang.String n0)"
     * @ejbgen:relation role-name="BandEJB-has-Recordings" cmr-field="recordings"
     *     target-ejb="Recording"
     *     multiplicity="One" name="Recording-BandEJB"
     * @ejbgen:relationship-caching-element caching-name="LoadRecordings" cmr-field="recordings"
     */
    abstract public class BandBean extends GenericEntityBean implements EntityBean
    {
       ...

### Nested Eager Loading of Relationships

For entity bean instances that are loaded as the result of eager loading of relationships, it is possible to in turn load their related beans. You can nest eager loading of relationships by using the id attribute on the top-level ejbgen:relationship-caching-element tag, and using the parent-id attribute on the nested tag. There is no limit to the number of levels you can nest, although in practice using multiple levels is likely going to negatively affect performance, due to the large number of beans that are being loaded.

Building on the example used above, recording beans also have a many-to-one bidirectional relationship with producer beans. That is, for each recording there is one producer (and for each producer there are many recordings). The following sample shows how to use the id and parent-id attributes to also load the producer for each recording that is returned by the BandBean's findByName query method. The BandBean definition is shown first:

     * @ejbgen:finder caching-name="LoadRecordings"
     *     ejb-ql="SELECT DISTINCT OBJECT(a) FROM BandEJB AS a WHERE a.name = ?1"
     *     signature="java.util.Collection findByName(java.lang.String n0)"
     * @ejbgen:relation role-name="BandEJB-has-Recordings" cmr-field="recordings"
     *     target-ejb="Recording"
     *     multiplicity="One" name="Recording-BandEJB"
     * @ejbgen:relationship-caching-element id="LR_ID" caching-name="LoadRecordings"
     *     cmr-field="recordings"
     */
    abstract public class BandBean extends GenericEntityBean implements EntityBean
    {
       ...

The RecordingBean defines the entity relationship with the ProducerBean, and an eager loading definition that is nested inside the BandBean's LoadRecordings eager loading definition, using the parent-id attribute:

     * @ejbgen:relation role-name="Recordings-have-Producer" fk-column="newColumn "
     *    cmr-field="producer" target-ejb="Producer"
     *    multiplicity="Many" name="Recording-Producer"
     * @ejbgen:relationship-caching-element caching-name="LoadProducer"
     *    cmr-field="producer" parent-id="LR_ID"
     */
    abstract public class RecordingBean extends GenericEntityBean implements EntityBean
    {
       ...

## Query Methods and Modified Data

In addition to eager loading of group-names and relationships, there is a third way to increase performance of query methods. In line with the EJB 2.0 specification, updates made by a transaction are by default reflected in the results of query methods that are subsequently invoked during the same transaction. This behavior is set by the include-updates attribute on the query method, that is, its ejbgen:finder or ejbgen:select tag.

If the include-updates attribute is set to true (or left unspecified), the EJB container saves all changes made at this point in the transaction to the database before executing the query. This guarantees that the changes show up in the query results but it also slows down performance. When this attribute is set to false, the updates of the current transaction are not reflected in the query. This results in better performance, although it does not necessarily guarantee the most current data to be returned by a query. However, you can safely set this attribute to false if within a transaction you do not re-query the data you just modified in that transaction, which is a common scenario.

Note. If the include-updates attribute is set to true (or left unspecified), changes are always stored before executing a query, thereby overriding the setting to wait until the end of a transaction before data is stored. However, if the transaction subsequently fails, any changes made during that transaction are still rolled back. For more information, see EJBs and Transactions.

## Using Read-Only Entity Beans

When you need to frequently read data from a table but you do not, or only very occasionally, have to write to this table, you can improve performance by creating a read-only bean. This read-only entity bean is used for all read operations, while the occasional write operations to the table is performed by another EJB. Make sure that the following attributes are set in the Property Editor for a read-only bean:

- The attribute concurrency-strategy is ReadOnly.
- The attribute cache-between-transactions is set to true.
- The attribute read-timeout-seconds should be set to an acceptable amount, depending on how often the cached data is updated.
- Make sure the related caching attributes idle-timeout-seconds and max-beans-in-cache are set to appropriate values.

All these attributes are part of the @ejbgen:entity Annotation. To learn more about caching between transactions, read the section below.

### Invalidating Read-Only Entity Beans

When the data that a read-only entity bean accesses is changed by the companion EJB with write operations, you might want to invalidate the read-only entity bean, thus forcing a refresh of the cache and ensuring that the read-only bean always returns the most current data.

To invalidate a read-only bean, you must set the 'write' entity bean's attribute invalidation-target, located in the Property Editor under Deployment, to the ejb-name of the read-only entity bean. This attribute is part of the @ejbgen:entity Annotation.

## Using Optimistic Concurrency

The Optimistic concurrency strategy for an entity bean entails that, unlike the Database or Exclusive strategy, no locks in the EJB container or database are placed during a transaction (also see the Bean Caching and Concurrency Options Summarized section below. To learn more about transactions, see EJBs and Transactions). The EJB container verifies that none of the data used by the transaction has been changed (by another source during another transaction) before committing the transaction. If the verified data has changed, the EJB container rolls back the transaction. The EJB container can verify that the used data has not changed in various ways, as specified by the verify-columns and verify-rows attributes on the ejbgen:entity tag. The options for the verify-columns attribute are as follows:

- Read. The EJB container checks all the columns in the table that have been read during the transaction. This most stringent option typically increases the amount of checking the EJB container must perform and lowers performance. However, it ensures that the data used in this transaction has not been changed in the mean-time.
- Modified. The EJB container checks only the columns that have been updated by the current transaction. This option typically increases performance, but it allows that columns that were not changed in the current transaction were changed in the meantime by another transaction. This interleaving of updates may or may not be desirable in all circumstances
- Version. The EJB container checks a version number on the record to verify that the record has not been changed. For more information, see below.
- TimeStamp. The EJB container checks a timestamp on the record to verify that the record has not been changed. For more information, see below.

Note. The EJB container does not check Oracle Blob/Clob fields for optimistic concurrency when using the Read or Modified option. Use version number or timestamp checking instead.

The options for the verify-rows attribute are as follows:

- Read. The EJB container checks any row that is read by the transaction. This most stringent option typically increases the amount of optimistic checking the EJB container must perform and lowers performance. However, it ensures that none of the data used in this transaction has been changed in the meantime.

  Note. If verify-rows is set to Read, verify-columns cannot be set to Modified.

- Modified. The EJB container checks only the rows that have been updated by the current transaction. This option typically increases performance, but it allows that rows that were not changed in the current transaction were changed in the meantime by another transaction. This interleaving of updates may or may not be desirable in all circumstances

Apart from the one noted exception, verify-rows and verify-columns work in conjunction. For instance, setting verify-columns to Read and verify-rows to Modified ensures that all columns of only modified rows are checked; Setting verify-columns to Version and verify-rows to Read means that all rows are checked via the version number; and so forth.

Note. If the EJB is mapped to multiple tables, optimistic checking is only performed on the tables that are updated during the transaction. In a clustered server environment, notifications for updates of optimistic data are broadcast to other cluster members to help avoid optimistic conflicts.

### Using a Version Number

When you specify the Version option on verify-columns, the EJB container checks via a version number that a record has not changed in the meantime by another transaction. The EJB container manages this version number, that is, it updates the version number of a record when its data has changed. However, you must define a version column in the database table to hold that version number. The column can be of type Integer or Long. In addition, you must indicate that this column is to be used for the version number by the EJB container, by specifying the column name in the optimistic-column attribute of the ejbgen:entity tag. Mapping this column to a cmp field in the entity bean is optional.

### Using a Timestamp

When you specify the Timestamp option on verify-columns, the EJB container checks via a time stamp that a record has not changed in the meantime by another transaction. The EJB container manages this time stamp, that is, it updates the time stamp of a record when its data has changed. However, you must define a column in the database table to hold that timestamp, which is an instance of java.sql.Timestamp. (The exact type of this column is database-dependent). In addition, you must indicate that this column is to be used for the timestamp by the EJB container, by specifying the column name in the optimistic-column attribute of the ejbgen:entity tag. Mapping this column to a cmp field in the entity bean is optional.

Note. When the EJB container updates a timestamp, it enforces at least a one-second difference between the old and new timestamp value.

## Using Caching Between Transactions

The EJB 2.0 architecture specifies that for entity beans, the CMP entity bean's are synchronized with the database before business methods are invoked. In WebLogic, this synchronization is specifically performed at the start of each transaction (directly after which the ejbLoad callback is invoked to notify the beans of the completed synchronization). When multiple sources may update the same data, synchronizing at this point ensures that the bean has the most current version of the data.

When only the EJB instance is guaranteed to ever access the data it represents, synchronizing repeatedly is unnecessary. Because no other clients or systems update the EJB's underlying data, the cached version of the EJB data is always up to date. To avoid these unnecessary synchronizations, you can set the ejbgen:entity cache-between-transactions attribute to true. When you set this attribute, synchronizations are only performed when:

- The entity bean does not yet exist in the cache. Its data is read from the database to fill the cache.
- The entity bean's transaction rolls back. Its data is read from the database to undo any changes made to the data within the rolled back transaction.
- The time to use cached data, as set by the read-timeout-seconds attribute, has expired, forcing a read from the database.
- The entity bean was cached but has been removed from the cache since then because its idle time exceeded the idle-timeout-seconds attribute.

Note. If you incorrectly set cache-between-transactions set to true, that is, if the data that the EJB maps can be changed by multiple sources, data integrity violations may result.

To set the maximum number of beans in the cache, you can set the max-beans-in-cache attribute. These and the other caching attributes are part of the @ejbgen:entity Annotation.

### Bean Caching and Concurrency Options Summarized

The concurrency strategy for an entity bean is set using the ejbgen:entity concurrency-strategy attribute, which can be done through the Property Editor. Similarly, in the Property Editor you can enable caching between transactions using the ejbgen:entity cache-between-transactions attribute, but enabling caching is not possible for all concurrency strategies. The following list gives an overview of the various valid combinations:

- Database. This is the default concurrency strategy. When data is used in a transaction, the EJB container allocates a separate entity bean to represent that data. Any required locking actions are not handled by the container but are deferred to the database.

  Using this concurrency strategy, the EJB container loads the latest data from the database at the beginning of the transaction. When the data is to be committed (just prior to calling the ejbStore callback), this request to store data is passed along to the database. The database handles all required lock management and provides deadlock detection.

  Deferring locks to the underlying database enables concurrent access to entity EJB data. However, using database locking requires more detailed knowledge of the underlying datastore's lock policies, which might reduce portability among different database systems. Also, the container never caches the intermediate state of the EJB instance between transactions. That is, setting the ejbgen:entity cache-between-transactions attribute to True is not a valid option for this concurrency strategy.

- Exclusive. The EJB container places an exclusive lock on the data represented by an entity bean instance when the bean is associated with a transaction. Any concurrent requests for the same data are blocked, even if it is a read-only request to this data, thus potentially greatly reducing performance.

  Using this concurrency strategy, you can either enable or disable caching between transactions. However, caching is not allowed for this concurrency strategy in a clustered server environment.

- ReadOnly. Used only for read-only entity beans. When you specify this concurrency strategy, you must also enable caching between transactions. For more information, see the Read-Only Entity Beans section above.
- Optimistic. When you specify this concurrency strategy, no locks in the EJB container or database are placed during a transaction. The EJB container verifies that none of the data used by the transaction has been changed (by another source) before committing the transaction. Using this concurrency strategy, you can either enable or disable caching between transactions. For more information, see the Using Optimistic Concurrency section above.

Note. Concurrency settings may affect transaction isolation levels. For more information, see EJBs and Transactions.

## Application-Level Caching

Application-level caching allows multiple entity beans that are part of the same application to share a single runtime cache. Application-level caching offers the following advantages:

- It reduces the number of entity bean caches, and hence the effort to configure the cache.
- It ensures better utilization of memory and heap space, because of reduced fragmentation. For instance, if a particular EJB experiences a burst of activity, it can make use of all memory available to the combined cache, while other EJBs that use the cache are paged out. If two EJBs use different caches, when one bean's cache becomes full, the container cannot page out EJBs in the other bean's cache
- It simplifies management, as application-level caching enables a system administrator to tune a single cache, instead of many caches.

Application-level caching is not the best choice, however, for applications that experience high throughput. Because one thread of control exists per cache at a time, high throughput can create a bottleneck situation as tasks compete for control of the thread.

### To Configure the Application-Level Cache

To create the application-level cache, you must manually edit weblogic-application.xml, located in the META-INF directory of your WebLogic application. Locate the ejb section of the file, and add the entity-cache within this section, as shown in the following example:

    <weblogic-application>
       <ejb>
          <entity-cache>
             <entity-cache-name>large_account</entity-cache-name>
             <max-cache-size>
                <megabytes>1</megabytes>
             </max-cache-size>
          </entity-cache>
       </ejb>
    </weblogic_application>

The most common xml elements for entity caches are:

- entity-cache. Defines the entity cache. You can define optionally more than one application level cache to cache entity beans.
- entity-cache-name. Specifies a unique name for an entity bean cache. The name must be unique within an ear file.
- max-beans-in-cache. This optional element specifies the maximum number of entity beans that are allowed in the application-level cache. If the limit is reached, beans may be passivated. The default is 1000. If 0 is specified, then there is no limit. This mechanism does not take into account the actual amount of memory that different entity beans require.
- max-cache-size. This optional element is used to specify a limit on the size of an entity cache in terms of memory size—expressed either in terms of bytes or megabytes.

For more information, see Enterprise Application Deployment Descriptor Elements.

### To Reference the Application-Level Cache

To use the application-level entity cache for an entity bean, you must add an @ejbgen:entity-cache-ref tag to its definition, and use the name attribute to refer to the application-level entity cache name. If you have specified the application-level cache maximum using the max-cache-size, instead of max-beans-in-cache, you should also use the tag's estimated-bean-size attribute to specify an estimated bean size. These estimates are primarily used to estimate the relative amounts of different entity bean instances that can be held in the application-level cache.

If you don't reference the application-level cache, a separate cache is used for the entity bean.

## Passing Method Arguments By Reference

When you invoke entity beans through their remote interfaces, WebLogic must pass method arguments by value (due to classloading requirements). When EJBs are invoked through their local interface, WebLogic can pass method arguments by reference, improving the performance of method invocation (because parameters are not copied).

In WebLogic passing arguments by value is done by default. To enable passing arguments by reference, you must set the ejbgen:entity enable-call-by-reference to True.

## Sorting and Batching Database Operations

When an entity bean is part of a transaction, the EJB container can take advantage of this by executing the SQL commands on the database table at the end of the transaction when the transaction commits instead of at various points during the transaction. (To learn more about transactions, see EJBs and Transactions). In addition, the EJB container can execute related changes in a single SQL instead of executing separate SQL commands for each individual change. The ejbgen:entity order-database-operations and ejbgen:entity enable-batch-operations attributes are used to enable this. By default, both attributes are set to True.

When database operations are ordered, insert, update and delete commands are sorted to ensure data consistency. These sorted database operations are executed at commit time instead of during the transaction. For instance, if during a transaction a customer receives a new credit card and the old credit card is destroyed, a reference is first made from the customer record to the new credit card record before the old credit card record is deleted. Reversing the order of the SQL commands would violate referential integrity.

If multiple instances of an entity bean are changed in the transaction, enabling batch operations increases performance by allowing the EJB container to update/insert/delete multiple records in the database at the same time instead of issuing separate SQL commands for each entity bean instance change.

Note. Batch operations are disabled if the transaction involves Automatic Primary Key Generation with SQL Server or an update to an OracleBlob or OracleClob CMP field (see the @ejbgen:cmp-field Annotation). The total number of instances inserted in a batch operation cannot exceed the entity bean's max-beans-in-cache attribute.

## Related Topics

@ejbgen:cmp-field Annotation

@ejbgen:cmr-field Annotation

@ejbgen:finder Annotation

@ejbgen:select Annotation

@ejbgen:entity Annotation