Skip Headers
Oracle® Application Server TopLink Application Developer's Guide
10g Release 2 (10.1.2)
Part No. B15901-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

Queries and the Cache

OracleAS TopLink caches objects written to and read from the database to maintain object identity. The sequence in which a query checks the cache and database affects query performance. By default, primary key queries check the cache before accessing the database, and all queries check the cache before rebuilding an object from its row.


Note:

You can override the default behavior in the caching policy configuration information in the OracleAS TopLink descriptor. For more information, see "Explicit Query Refreshes" .

This section illustrates ways to manipulate the query-cache relationship, including:

Cache Usage

OracleAS TopLink maintains a client-side cache to reduce the number of reads required from the database.

Cache and the Database

The cache in an OracleAS TopLink application holds objects that have already been read from or written to the database. Use of the cache in an OracleAS TopLink application reduces the number of accesses to the database. Because accessing the database is a time-intensive and resource-intensive act, an effective caching strategy is important to the efficiency of your application.

For more information about configuring and using the cache, see Chapter 8, "Cache".

In-Memory Query Cache Usage

In-memory querying enables you to perform queries on the cache rather than the database. In-memory querying supports the following relationships:

  • One-to-one

  • One-to-many

  • Many-to-many

  • Aggregate collection

  • Direct collection


    Note:

    By default, the relationships themselves must be in memory for in-memory traversal to work. Ensure that you trigger all valueholders to enable in-memory querying to work across relationships.

You can configure in-memory query cache usage at the query level for both readObject and readAll queries. OracleAS TopLink supports the following in-memory query features:

  • checkCacheByPrimaryKey(): The default setting. If a read object query contains an expression that compares at least the primary key, then you can obtain a cache hit if you process the expression against the objects in memory.

  • checkCacheByExactPrimaryKey(): If a read object query contains an expression where the primary key is the only comparison, you can obtain a cache hit if you process the expression against the object in memory.

  • checkCacheThenDatabase(): You can configure any read object query to check the cache completely before you resort to accessing the database.

  • checkCacheOnly(): You can configure any read all query to check only the cache and return the result from the cache without accessing the database.

  • conformResultsInUnitOfWork(): You can configure any read object or read all query within the context of a Unit of Work to conform the results with the changes to the object made within that Unit of Work. This includes new objects, deleted objects and changed objects.

Table 6-6 identifies the in-memory queries options OracleAS TopLink supports.

Table 6-6 In-Memory Queries OracleAS TopLink Supports

Type Query OracleAS TopLink Supports
Comparators equal(..)

notEqual(..)

like(..)

lessThan(..)

lessThanOrEqual(..)

greaterThan(..)

greaterThanOrEqual(..)

between(...)

notBetween(...)

isNull()

notNull()

in(...)

Logical operators or(..)

and(..)

Joining get(..)

getAllowingNull(..)

anyOf(..)

anyOfAllowingNone(..)


Handling Exceptions Resulting from In-Memory Queries

In-memory queries fail for several reasons, the most common being:

  • The query expression is too complex to execute in memory.

  • There are untriggered valueholders in which indirection is used. All object models that use indirection must first trigger valueholders before they conform on the relevant objects.

OracleAS TopLink provides a mechanism to handle indirection exceptions. To specify how the application must handle these exceptions, use InMemoryQueryIndirectionPolicy class:

  • Should throw indirection exception: The default setting. It is the only setting that throws indirection exceptions.

  • Should trigger indirection: Triggers all valueholders to eliminate the problem.

  • Should ignore exception return conformed: Returns conforming if an untriggered valueholder are encountered.

  • Should ignore exception return not conformed: Returns not conforming if an untriggered valueholder is encountered.


    Note:

    When you build new applications, consider throwing all conform exceptions. This provides more detailed feedback for unsuccessful in-memory queries.

Conforming Results (UnitOfWork)

You can conform query results in the Unit of Work across one-to-many, as well as a combination of one-to-one and one-to-many relationships. The following is an example of a query across two levels of relationships, one-to-many and one-to-one.

Expression exp = 
  bldr.anyOf("managedEmployees").get("address").get("city").equal("Perth");


Note:

When relationships in an in-memory query use indirection, trigger all valueholders to ensure that the objects are available in the cache.

Exceptions thrown by the conform feature are masked by default. However, OracleAS TopLink includes an API that allows exceptions to be thrown rather than masked. The API is: uow.setShouldThrowConformExceptions(ARGUMENT).

ARGUMENT is an integer with one of the following values:

  • Do not throw conform exceptions (default)

  • Throw all conform exceptions

For more information, see "Validating a Unit of Work".

Cache and the Primary Key

When a query searches for a single object by primary key, OracleAS TopLink extracts the primary key from the query and attempts to return the object from the cache without accessing the database. If the object is not in the cache, then the query executes against the database, builds the resulting objects, and places them in the identity map.

If the query is based on a non-primary key selection criteria or is a readAll query, then the query executes against the database (unless you have selected the checkCacheOnly() option). The query matches primary keys from the result set to objects in the cache and returns the cached objects, if any, in the result set.

If an object is not in the cache, OracleAS TopLink builds the object. If the query is a refreshing query, OracleAS TopLink updates the contents of any objects with the results from the query. Use Object identity (==) if you properly configure and use an identity map.

Clients can refresh objects when they want to ensure that they have the latest data at a particular time.

Disabling the Identity Map Cache Update During a Read Query

To disable the identity map cache update, which is normally performed by a read query, call the dontMaintainCache() method. This improves the query performance when you read objects that are not needed later by the application.

Example 6-59 Disabling the Identity Map Cache Update

This example demonstrates how code reads Employee objects from the database and writes the information to a flat file.

// Reads objects from the employee table and writes them to an employee file. 
void writeEmployeeTableToFile(String filename, Session session)
{
    Vector employeeObjects;
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Employee.class);
    query.setSelectionCriteria(new     ExpressionBuilder.get("id").greaterThan(100)); 
    query.dontMaintainCache();
    Vector employees = (Vector) session.executeQuery(query);
    // Write all the employee data to a file.
    Employee.writeToFile(filename, employees);
}

Refresh

You can refresh objects in the cache to ensure that they are current with the database while preserving object identity.

Object Refresh

To refresh objects in the cache with the data in the database, call the session.refreshObject() method or the readObjectQuery.setShouldRefreshIdentityMapResult(true) method.

Cascading Object Refresh

You can control the depth at which a refresh updates objects and their related objects. There are three options:

  • CascadePrivateParts: Default refresh behavior. Refreshes the local level object and objects that are referenced in privately owned, nonindirect, relationships.

  • CascadeNone: Refreshes only the first level of the object, but does not refresh related objects.

  • CascadeAll: Refreshes the entire object tree, stopping when it either reaches the leaf objects or when it encounters untriggered indirection in the tree.

Refreshing the Identity Map Cache During a Read Query

Include the refreshIdentityMapResult() method in a query to force an identity map refresh with the result of the query.

Example 6-60 Refreshing the Result of a Query in the Identity Map Cache During a Read Query

ReadObjectQuery query = new ReadObjectQuery();
query.setReferenceClass(Employee.class);
query.setSelectionCriteria(new ExpressionBuilder().get("lastName").equal("Smith")); 
query.refreshIdentityMapResult();
Employee employee = (Employee) session.executeQuery(query);

The refreshIdentityMapResult() method refreshes the attributes of the object, but not the attributes of its privately owned parts. However, under most circumstances, refresh the privately owned parts of the object and other related objects to ensure consistency with the database.

To refresh privately owned or related parts, use the following methods:

  • cascadePrivateParts(): refreshes all privately owned objects

  • cascadeAllParts(): refreshes all related objects

Example 6-61 Using the cascadePrivateParts Method

ReadAllQuery query = new ReadAllQuery();
query.setReferenceClass(Employee.class);
query.refreshIdentityMapResult();
query.cascadePrivateParts();
Vector employees = (Vector) session.executeQuery(query);


Note:

If the object is in the session cache, then you can also use the refreshObject() method to refresh an object and its privately owned parts.

Caching Query Results

When an application executes a query, you can store the results of that query in the cache. This is useful for frequently executed queries that run against static data. Caching the results also ensures that the query returns the same results for a given period of time (for example, within the scope of a particular transaction) and then refreshes the data later if required.