Cayenne provides a way to cache query results, avoiding unneeded database trips for the frequently used queries. Caching policy is configured per query. Policy can be set via the API or in CayenneModeler.
|Upgrading to Cayenne 1.2 and Newer|
org.objectstyle.cayenne.query.GenericSelectQuery interface that defined cache policy types is deprecated. Cache policies are now a part of the new org.objectstyle.cayenne.query.QueryMetadata interface.
The following cache policies are supported:
|Policy||Cache Scope||Cache Behavior|
|(default policy) QueryMetadata.NO_CACHE||N/A||Always fetch, never use cache, never save to cache|
|QueryMetadata.LOCAL_CACHE||DataContext||If result is previously cached, use it, otherwise do a fetch and store result in cache for future use|
|QueryMetadata.LOCAL_CACHE_REFRESH||DataContext||Never use cache, alwyas do a fetch and store result in cache for future use|
|QueryMetadata.SHARED_CACHE||DataDomain (usually shared by all contexts in the same JVM)||If result is previously cached, use it, otherwise do a fetch and store result in cache for future use|
|QueryMetadata.SHARED_CACHE_REFRESH||DataDomain (usually shared by all contexts in the same JVM)||Never use cache, alwyas do a fetch and store result in cache for future use|
It is important to understand that caching of result lists is done independently from caching of individual DataObjects and DataRows. Therefore the API is different as well. Also cached results lists are not synchronized across VMs (even the shared cache).
Users must set two Query parameters to configure caching - query name that is used as a key to result cache and query cache policy (one of the policies above). Note that if two unrelated queries have the same name, they will hit the same cache entry. This is not a bug, this is a feature that should be taken into consideration when naming queries.
Below we will create a query and set its caching policy to LOCAL_CACHE:
Reruning the query in the same DataContext at a later time will be much faster as it will be hitting the cache:
Here we want to refresh the cache, but still keep caching the fresh result:
The example above shows caching with SelectQuery, but it works exactly the same way for SQLTemplate and ProcedureQuery. Similarly SHARED_CACHE and SHARED_CACHE_REFRESH cache policies create cache shared by all DataDontexts that work with a given DataDomain.
|Upgrading to Cayenne 1.2 and Newer|
Cache refreshing API has changed in 1.2. Cayenne 1.1 relied on the use of SelectQuery.setRefreshingObjects(..) to determine whether to expire cached result lists. This is no longer the case (setting this flag only refreshes individual objects as it should, and has no effect whatsoever on list caching). Instead caching and cache refreshing is controlled by the cache policy as described above.
The easiest way to set up caching is by creating a named query in CayenneModeler with the appropriate caching type.
Then it can be executed via DataContext:
The second "false" parameter above indicated that if possible, cached result should be used. Now if we want to force refresh, it can be changed to true (for just this invocation - this does not affect the underlying saved query)
Note that parameterized named queries will still work correctly with the cache. We've already mentioned that the users must ensure that two queries must have different names if they fetch logically different data. This is NOT the case with queries stored in the DataMap. If you run the same named query with different sets of parameters, Cayenne will internally generate unique cache keys for each distinct parameter set.
Now if we run the same query with a different set of parameters, Cayenne will do the right thing and create a separate entry in the cache: