Cayenne provides a way to cache query results, avoiding unneeded database trips for the frequently used queries. Caching strategy is configured per query. A strategy can be set via API or in CayenneModeler. Possible strategies, as defined in the org.apache.cayenne.query.QueryCacheStrategy enum are the following:
|Policy||Cache Scope||Cache Behavior|
|(default) NO_CACHE||N/A||Always fetch, never use cache, never save to cache|
|LOCAL_CACHE||ObjectContext||If result is previously cached, use it, otherwise do a fetch and store result in cache for future use|
|LOCAL_CACHE_REFRESH||ObjectContext||Never use cache, always do a fetch and store result in cache for future use|
|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|
|SHARED_CACHE_REFRESH||DataDomain (usually shared by all contexts in the same JVM)||Never use cache, always 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).
When creating queries in the code, users may set a desired cache strategy per query. Below we will create a query and set its caching policy to LOCAL_CACHE:
Now if we rerun the same query (or create a new instance of the query with the same set of parameters), we'll get cached result, which will be much faster than fetching it from DB.
The point about 2 separate queries reusing the same cache entry is worth repeating. A cache key for each query is automatically generated by Cayenne based on the type of the query and its parameters (such as qualifier, ordering, etc.). So a query itself does not need to be cached by the user code for future reuse. New queries can be created as needed.
Or if we want to refresh the cache, but still keep caching the result after that:
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 ObjectContexts that work on top of a given DataDomain.
There's another optional query property called "cacheGroups" that allows to fine-tune cache expiration in a declarative fashion. When creating a query, a user would specify the names of the cache groups (which are really cache expiration groups) associated with this query, and then separately define expiration policies for the cache groups present in the application. See Query Result Caching for more details.
Named queries created in CayenneModeler can also be configured to use caching, with the same cache strategy and cache groups parameters:
NamedQueries that are using caching can be executed just like any other NamedQuery.