The Loading Process


In the previous sections, several times we use the phrase "when an entity is loaded." This is intentionally left vague because the commit option specified for the entity and the current state of the transaction determine when an entity is loaded. The following sections describe the commit options and the loading processes.

Commit Options

Central to the loading process are the commit options, which control when the cached data for an entity expires. JBoss supports four commit options: A, B, C, and D. The first three are described in the Enterprise JavaBeans specification, but the last one is specific to JBoss. Detailed descriptions of the commit options follow:

  • A JBoss assumes that it is the sole user of the database; therefore, JBoss can cache the current value of an entity between transactions, which can result is substantial performance gains. As a result of this assumption, no data managed by JBoss can be changed outside JBoss. For example, changing data in another program or with the use of direct JDBC (even within JBoss) result in an inconsistent database state.

  • B JBoss assumes that there is more than one user of the database but keeps the context information about entities between transactions. This context information is used for optimizing loading of the entity. This is the default commit option.

  • C JBoss discards all entity context information at the end of the transaction.

  • D This is a JBoss-specific commit option. This option is similar to commit option A, except that the data remains valid for only a specified amount of time.

The commit option is declared in the jboss.xml file. For a detailed description of this file, see Chapter 5, "EJBs on JBoss." The example shown in Listing 11.2 changes the commit option to A for all entity beans in the application.

Listing 11.2. The jboss.xml Commit Option Declaration
 <jboss>     <container-configurations>         <container-configuration>             <container-name>Standard CMP 2.x EntityBean</container-name>             <commit-option>A</commit-option>         </container-configuration>     </container-configurations> </jboss> 

The Eager-Loading Process

When an entity is loaded, JBoss must determine what fields need to be loaded. By default, JBoss uses the eager-load-group of the last query that selected this entity. If the entity has not been selected in a query, or if the last query uses the none read-ahead strategy, JBoss uses the default eager-load-group declared for the entity. In the following configuration example, the basic load group is set as the default eager-load-group for the gangster entity bean:

 <jbosscmp-jdbc>     <enterprise-beans>         <entity>             <ejb-name>GangsterEJB</ejb-name>             <!-- ... -->             <load-groups>                 <load-group>                     <load-group-name>most</load-group-name>                     <field-name>name</field-name>                     <field-name>nickName</field-name>                     <field-name>badness</field-name>                     <field-name>hangout</field-name>                     <field-name>organization</field-name>                 </load-group>             </load-groups>             <eager-load-group>most</eager-load-group>         </entity>     </enterprise-beans> </jbosscmp-jdbc> 

The eager-loading process is initiated the first time a method is called on an entity in a transaction. The load process is as follows:

1.

If the entity context is still valid, no loading is necessary, and therefore the loading process is done. The entity context is valid when you use commit option A or commit option D and the data has not timed out.

2.

Any residual data in the entity context is flushed. This ensures that old data does not bleed into the new load.

3.

The primary key value is injected back into the primary key fields. The primary key object is actually independent of the fields and needs to be reloaded after the flush in step 2.

4.

All data in the preload cache for this entity is loaded into the fields.

5.

JBoss determines what additional fields still need to be loaded. Normally, the fields to load are determined by the eager-load group of the entity, but this can be overridden if the entity is located by using a query or CMR field with an on-find or on-load read-ahead strategy. If all the fields have already been loaded, the load process skips to step 7.

6.

A query is executed to select the necessary column. If this entity uses the on-load strategy, a page of data is loaded, as described in the section "The on-load Strategy," earlier in this chapter. The data for the current entity is stored in the context, and the data for the other entities is stored in the preload cache.

7.

The ejbLoad method of the entity is called.

The Lazy-Loading Process

Lazy loading is the other half of eager loading. If a field is not eager loaded, it must be lazy loaded. When an access to an unloaded field of a bean is made, JBoss loads the field and all the fields of any lazy-load-group the field belong to. JBoss performs a set join and then removes any field that is already loaded. A configuration example is shown here:

 <jbosscmp-jdbc>     <enterprise-beans>         <entity>             <ejb-name>GangsterEJB</ejb-name>             <!-- ... -->             <load-groups>                 <load-group>                     <load-group-name>most</load-group-name>                     <field-name>name</field-name>                     <field-name>nickName</field-name>                     <field-name>badness</field-name>                     <field-name>hangout</field-name>                     <field-name>organization</field-name>                 </load-group>             </load-groups>             <eager-load-group>most</eager-load-group>         </entity>     </enterprise-beans> </jbosscmp-jdbc> 

When the bean provider calls getName() with this configuration, JBoss loads name, nickName, and badness, assuming that they are not already loaded. When the bean provider calls getNickName(), the name, nickName, badness, contactInfo, and hangout are loaded. The lazy-loading process is as follows:

1.

All data in the preload cache for this entity is loaded into the fields.

2.

If the field value was loaded by the preload cache, the lazy-load process is finished.

3.

JBoss finds all the lazy-load groups that contain this field, performs a set join on the groups, and removes any field that has already been loaded.

4.

A query is executed to select the necessary columns. As in the basic load process, JBoss may load a block of entities. The data for the current entity is stored in the context, and the data for the other entities is stored in the preload cache.

Relationships

Relationships are a special case in lazy loading because a CMR field is both a field and a query. As a field, it can be on-load block loaded, meaning that the value of the currently sought entity and the values of the CMR field for the next several entities are loaded. As a query, the field values of the related entity can be preloaded by using on-find.

Again, the easiest way to investigate the loading is to look at a usage scenario. Listing 11.3 generates an HTML table that contains each gangster and his hangout.

Listing 11.3. Relationship Lazy-Loading Sample Code
 public String createGangsterHangoutHtmlTable()     throws FinderException {     StringBuffer table = new StringBuffer();     table.append("<table>");     Collection gangsters = gangsterHome.findAll_onfind();     for (Iterator iter = gangsters.iterator(); iter.hasNext(); ) {         Gangster gangster = (Gangster)iter.next();         Location hangout = gangster.getHangout();         table.append("<tr>");         table.append("<td>").append(gangster.getName());         table.append("</td>");         table.append("<td>").append(gangster.getNickName());         table.append("</td>");         table.append("<td>").append(gangster.getBadness());         table.append("</td>");         table.append("<td>").append(hangout.getCity());         table.append("</td>");         table.append("<td>").append(hangout.getState());         table.append("</td>");         table.append("<td>").append(hangout.getZipCode());         table.append("</td>");         table.append("</tr>");     }     table.append("</table>");return table.toString(); } 

For this example, the configuration of the gangster's findAll_onfind query is unchanged from what is described earlier in this chapter. The configuration of the Location entity and Gangster-Hangout relationship is shown in Listing 11.4.

Listing 11.4. The jbosscmp-jdbc.xml Relationship Lazy-Loading Configuration
 <jbosscmp-jdbc>     <enterprise-beans>         <entity>             <ejb-name>LocationEJB</ejb-name>             <load-groups>                 <load-group>                     <load-group-name>quick info</load-group-name>                     <field-name>city</field-name>                     <field-name>state</field-name>                     <field-name>zipCode</field-name>                 </load-group>             </load-groups>             <eager-load-group/>         </entity>     </enterprise-beans>     <relationships>         <ejb-relation>             <ejb-relation-name>Gangster-Hangout</ejb-relation-name>             <foreign-key-mapping/>             <ejb-relationship-role>                 <ejb-relationship-role-name>                     gangster-has-a-hangout                 </ejb-relationship-role-name>                 <key-fields/>                 <read-ahead>                     <strategy>on-find</strategy>                     <page-size>4</page-size>                     <eager-load-group>quick info</eager-load-group>                 </read-ahead>             </ejb-relationship-role>             <ejb-relationship-role>                 <ejb-relationship-role-name>                     hangout-for-a-gangster                 </ejb-relationship-role-name>                 <key-fields>                     <key-field>                         <field-name>locationID</field-name>                         <column-name>hangout</column-name>                     </key-field>                 </key-filaelds>             </ejb-relationship-role>         </ejb-relation>     </relationships> </jbosscmp-jdbc> 

JBoss executes the following query for the finder:

 SELECT t0_g.id, t0_g.name, t0_g.nick_name, t0_g.badness     FROM gangster t0_g     ORDER BY t0_g.id ASC 

Then when the hangout is accessed, JBoss executes the following two queries to load the city, state, and zip fields of the hangout:

 SELECT gangster.id, gangster.hangout,        location.city, location.st, location.zip     FROM gangster, location     WHERE (gangster.hangout=location.id) AND           ((gangster.id=0) OR (gangster.id=1) OR           (gangster.id=2) OR (gangster.id=3)) SELECT gangster.id, gangster.hangout,        location.city, location.st, location.zip     FROM gangster, location     WHERE (gangster.hangout=location.id) AND           ((gangster.id=4) OR (gangster.id=5) OR           (gangster.id=6) OR (gangster.id=7)) 

Table 11.4 shows the execution of the queries.

Table 11.4. on-find Optimized Relationship Query Execution

id name

nick_name

badness

hangout

id

city

st

zip

0 Yojimbo

Bodyguard

7

0

0

San Fran

CA

94108

1 Takeshi

Master

10

1

1

San Fran

CA

94133

2 Yuriko

Four finger

4

2

2

San Fran

CA

94133

3 Chow

Killer

9

3

3

San Fran

CA

94133

4 Shogi

Lightning

8

4

4

San Fran

CA

94133

5 Valentino

Pizza-Face

4

5

5

New York

NY

10017

6 Toni

Toothless

2

6

6

Chicago

IL

60661

7 Corleone

Godfather

6

7

7

Las Vegas

NV

89109


Lazy-Loading Result Sets

By default, when a multi-object finder or select method is executed, the JDBC result set is read to the end immediately. The client receives a collection of EJBLocalObject or CMP field values that it can then iterate through. For big result sets, this approach is not efficient. In some cases, it is better to delay reading the next row in the result set until the client tries to read the corresponding value from the collection. You can get this behavior for a query by using the lazy-resultset-loading element:

 <query>     <query-method>         <method-name>findAll</method-name>     </query-method>     <jboss-ql><![CDATA[select object(o) from A o]]></jboss-ql>     <lazy-resultset-loading>true</lazy-resultset-loading> </query> 

There are some issues you should be aware of when using lazy result set loading. You need to take special care when working with a Collection associated with a lazily loaded result set. The first call to iterator() returns a special Iterator that reads from the ResultSet. Until this Iterator has been exhausted, subsequent calls to iterator() or calls to the add() method result in an exception. The remove() and size() methods work as you would expected.



JBoss 4. 0(c) The Official Guide
JBoss 4.0 - The Official Guide
ISBN: B003D7JU58
EAN: N/A
Year: 2006
Pages: 137

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net