Enterprise Objects supports a number of advanced fetching techniques.
Prefetching
Entity Caching
Raw Row Fetching
Raw SQL Fetching
As described in “Faulting and Relationship Resolution,” when Enterprise Objects fetches an enterprise object, it creates faults for the object’s relationships. Each time a fault is fired, a round trip is made to the database to retrieve the fault’s data. You can batch together fault firing as described in “Batch Faulting” to reduce the number of round trips to the database. However, you can go even further in reducing the number of round trips to the database by prefetching all the objects in a particular relationship. Prefetching allows you to anticipate that some of an enterprise object’s relationships will be fetched and provides a mechanism to preload them; it provides a performance opportunity.
For example, consider a Listing entity that has an agent relationship. When you fetch twenty Listing objects, faults are created for each Listing’s agent relationship. When the data in the agent relationship is accessed for a particular Listing object, a fault is fired to retrieve the relationship’s data, which invokes a round trip to the database. Implementing batch faulting reduces the number of round trips but you can further reduce the number of round trips by simply prefetching all of the agent data in the database. With prefetching, when a fetch is performed for a particular entity, the objects in the relationships specified by the prefetching key paths (agent in this case) are immediately fetched.
You instrument your application for prefetching by configuring certain fetch specifications for prefetching. You can use the Prefetching pane of EOModeler’s fetch specification builder to configure it for a particular fetch specification or you can invoke setPrefetchingRelationshipKeyPaths on a fetch specification, which takes an array of strings representing the relationships to prefetch.
There are a few guidelines to consider when using prefetching. First, if memory usage is an issue for your application rather than database performance, don’t use prefetching as it consumes more memory. In fact, prefetching can consume an inordinate amount of memory depending on the size of the data set, so it’s probably more appropriate to prefetch only those relationships that have a small number of destination objects.
Second, don’t use prefetching on a fetch specification that uses a fetch limit. The prefetching hint ignores the fetch limit.
Third, don’t use prefetching when performing multiple queries that return the same records. The performance benefits of prefetching are negated by the overhead of re-creating enterprise objects of the same rows of data multiple times.
Many applications have read-only entities that contain static data such as lists of states and countries, building names, or department names. Since many users of an application use the data in these entities, it makes sense to cache the data in memory to reduce the number of fetches to the database. In Enterprise Objects, you can cache an entire table in memory, thereby eliminating unnecessary fetches for the same static data by multiple users.
To enable entity caching for an entity, select the Cache In Memory option in EOModeler’s advanced entity inspector for a particular entity, as shown in “Figure 6-7.” You can enable this option programmatically using the method setCachesObjects on EOEntity.
When entity caching is enabled for a particular entity, the first fetch of that entity’s table causes the whole table to be fetched into memory. Clearly, this option is appropriate only for tables with a small number of rows.
An entity’s cache of objects is maintained by an EODatabaseContext. If you provide a separate access layer stack for each user as described in “Providing Separate Stacks,” each session has its own EODatabaseContext, so bear in mind that entity caching in this scenario may consume a lot of memory.
Fetch specifications provide an option to fetch raw rows. When you use raw row fetching, database rows that are fetched are not automatically transformed into enterprise object instances. There are a number of reasons why you’d want to specify raw row fetching for a particular fetch specification. These include:
reducing memory usage when fetching large data sets
improving application performance when fetching large data sets
reducing the general overhead of an application instance
You can specify raw row fetching for a particular fetch specification either in EOModeler’s fetch specification builder or by invoking the method setFetchesRawRows on a fetch specification. You can more closely control which rows are fetched as raw rows using the method setRawRowKeyPaths on a fetch specification.
When you fetch raw rows, you lose many of the benefits of using full-fledged enterprise object instances such as the object graph, change notifications, and so forth. But many of the cases in which you need to fetch raw rows involve fetching large data sets that don’t need the benefits of the object graph, so this is an acceptable trade-off in light of the performance benefits of raw row fetching.
Plus, you can always instantiate an enterprise object of that row using the method faultForRawRow on an EOEditingContext.
Although fetch specifications are the most common type of objects used to fetch data in Enterprise Objects applications, a lighter-weight mechanism is also provided that fetches raw rows based on an SQL expression you provide. This mechanism is provided as a method called rawRowsForSQL on the EOUtilities class. You pass to the method as arguments an editing context, a String representing the model that contains the entities on which to perform to the fetch, and a valid SQL expression. The results are returned as raw rows rather than as full-fledged enterprise objects.
Last updated: 2007-07-11