cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Cayenne Documentation > Caching Query Results
Date Sun, 20 Feb 2011 14:13:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2036/9/1/_/styles/combined.css?spaceKey=CAYDOC&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CAYDOC/Caching+Query+Results">Caching
Query Results</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~andrus">Andrus
Adamchik</a>
    </h4>
        <br/>
                         <h4>Changes (29)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-changed-lines" >Cayenne provides a way to cache
query results, avoiding unneeded database trips for the frequently used queries. Caching <span
class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">policy</span>
<span class="diff-added-words"style="background-color: #dfd;">strategy</span>
is configured per query. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Policy</span>
<span class="diff-added-words"style="background-color: #dfd;">A strategy</span>
can be set via <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">the</span>
API or in CayenneModeler. <span class="diff-added-words"style="background-color: #dfd;">Possible
strategies, as defined in the {{org.apache.cayenne.query.QueryCacheStrategy}} enum are the
following:</span> <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{note:title=Upgrading
to Cayenne 1.2 and Newer}{{org.apache.cayenne.query.GenericSelectQuery}} interface that defined
cache policy types is deprecated. Cache policies are now a part of the new {{org.apache.cayenne.query.QueryMetadata}}
interface.{note} <br> <br>The following cache policies are supported: <br>
<br></td></tr>
            <tr><td class="diff-unchanged" >||Policy||Cache Scope||Cache Behavior||
<br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-changed-words">|_(default<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">
policy</span>)_ {{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">QueryMetadata.</span>NO_CACHE}}</span>
|N/A|Always fetch, never use cache, never save to cache| <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">|{{QueryMetadata.LOCAL_CACHE}}|DataContext|If</span>
<span class="diff-added-words"style="background-color: #dfd;">|{{LOCAL_CACHE}}|ObjectContext|If</span>
result is previously cached, use it, otherwise do a fetch and store result in cache for future
use| <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">|{{QueryMetadata.LOCAL_CACHE_REFRESH}}|DataContext|Never</span>
<span class="diff-added-words"style="background-color: #dfd;">|{{LOCAL_CACHE_REFRESH}}|ObjectContext|Never</span>
use cache, <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">alwyas</span>
<span class="diff-added-words"style="background-color: #dfd;">always</span> do
a fetch and store result in cache for future use| <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-changed-words">|{{<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">QueryMetadata.</span>SHARED_CACHE}}|DataDomain</span>
(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| <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-changed-words">|{{<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">QueryMetadata.</span>SHARED_CACHE_REFRESH}}|DataDomain</span>
(usually shared by all contexts in the same JVM)|Never use cache, <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">alwyas</span>
<span class="diff-added-words"style="background-color: #dfd;">always</span> do
a fetch and store result in cache for future use| <br></td></tr>
            <tr><td class="diff-unchanged" > <br>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). <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h3. API for Result Caching <br>
<br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">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. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">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: <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Below
we will create a query and set its caching policy to LOCAL_CACHE: <br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br>SelectQuery query
= new SelectQuery(Artist.class); <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">//
set query name that will be used as a unique key to perform result caching <br>query.setName(&quot;MySelect&quot;);
<br> <br></td></tr>
            <tr><td class="diff-changed-lines" >// set local cache <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">policy,</span>
<span class="diff-added-words"style="background-color: #dfd;">strategy,</span>
meaning the cache will be stored in the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">DataContext</span>
<span class="diff-added-words"style="background-color: #dfd;">ObjectContext</span>
<br></td></tr>
            <tr><td class="diff-unchanged" >// and not shared between different
contexts <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">query.setCachePolicy(GenericSelectQuery.LOCAL_CACHE);</span>
<span class="diff-added-words"style="background-color: #dfd;">query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);</span>
<br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">DataContext</span>
<span class="diff-added-words"style="background-color: #dfd;">ObjectContext</span>
context = ... // assume this exists <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">//
there is probably no cache at this point, so the query will hit the database <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">//
if there was no cache at this point, the query will hit the database,  <br>// and will
store the result in the cache <br></td></tr>
            <tr><td class="diff-unchanged" >List objects = context.performQuery(query);
<br>{code} <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Reruning
the query in the same DataContext at a later time will be much faster as it will be hitting
the cache: <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Now
if we rerun the same query (or create a new instance of the query with the same set of parameters),
we&#39;ll get cached result, which will be much faster than fetching it from DB.  <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{code}
<br>List objects1 = context.performQuery(query); <br>{code} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">.bq
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. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Here
we want to refresh the cache, but still keep caching the fresh result: <br>{code} <br>query.setCachePolicy(GenericSelectQuery.LOCAL_CACHE_REFRESH);
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{code}//
creating a new query, same as the previous one <br>SelectQuery query1 = new SelectQuery(Artist.class);
<br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">List
objects2 = context.performQuery(query); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">//
this will hit the local cache <br>List objects1 = context.performQuery(query1); <br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">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.  <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Or
if we want to refresh the cache, but still keep caching the result after that: <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{code}query1.setCachePolicy(QueryCacheStrategy.LOCAL_CACHE_REFRESH);
<br>List objects2 = context.performQuery(query1); <br>{code} <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{note:title=Upgrading
to Cayenne 1.2 and Newer} <br>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.{note} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">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.  <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-unchanged" >h3. Queries Mapped in CayenneModeler
<br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>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 <tt>org.apache.cayenne.query.QueryCacheStrategy</tt>
enum are the following:</p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Policy</th>
<th class='confluenceTh'>Cache Scope</th>
<th class='confluenceTh'>Cache Behavior</th>
</tr>
<tr>
<td class='confluenceTd'><em>(default)</em> <tt>NO_CACHE</tt>
</td>
<td class='confluenceTd'>N/A</td>
<td class='confluenceTd'>Always fetch, never use cache, never save to cache</td>
</tr>
<tr>
<td class='confluenceTd'><tt>LOCAL_CACHE</tt></td>
<td class='confluenceTd'>ObjectContext</td>
<td class='confluenceTd'>If result is previously cached, use it, otherwise do a fetch
and store result in cache for future use</td>
</tr>
<tr>
<td class='confluenceTd'><tt>LOCAL_CACHE_REFRESH</tt></td>
<td class='confluenceTd'>ObjectContext</td>
<td class='confluenceTd'>Never use cache, always do a fetch and store result in cache
for future use</td>
</tr>
<tr>
<td class='confluenceTd'><tt>SHARED_CACHE</tt></td>
<td class='confluenceTd'>DataDomain (usually shared by all contexts in the same JVM)</td>
<td class='confluenceTd'>If result is previously cached, use it, otherwise do a fetch
and store result in cache for future use</td>
</tr>
<tr>
<td class='confluenceTd'><tt>SHARED_CACHE_REFRESH</tt></td>
<td class='confluenceTd'>DataDomain (usually shared by all contexts in the same JVM)</td>
<td class='confluenceTd'>Never use cache, always do a fetch and store result in cache
for future use</td>
</tr>
</tbody></table>
</div>


<p>It is important to understand that caching of <b>result lists</b> is
done independently from caching of <b>individual DataObjects and DataRows</b>.
Therefore the API is different as well. Also cached results lists are not synchronized across
VMs (even the shared cache).</p>

<h3><a name="CachingQueryResults-APIforResultCaching"></a>API for Result
Caching</h3>

<p>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:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
SelectQuery query = <span class="code-keyword">new</span> SelectQuery(Artist.class);

<span class="code-comment">// set local cache strategy, meaning the cache will be stored
in the ObjectContext 
</span><span class="code-comment">// and not shared between different contexts
</span>query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);

ObjectContext context = ... <span class="code-comment">// assume <span class="code-keyword">this</span>
exists
</span>
<span class="code-comment">// <span class="code-keyword">if</span> there
was no cache at <span class="code-keyword">this</span> point, the query will hit
the database, 
</span><span class="code-comment">// and will store the result in the cache
</span>List objects = context.performQuery(query);
</pre>
</div></div>

<p>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. </p>

<p>.bq 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.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-comment">// creating a <span class="code-keyword">new</span>
query, same as the previous one
</span>SelectQuery query1 = <span class="code-keyword">new</span> SelectQuery(Artist.class);

<span class="code-comment">// <span class="code-keyword">this</span> will
hit the local cache
</span>List objects1 = context.performQuery(query1);
</pre>
</div></div>

<p>Or if we want to refresh the cache, but still keep caching the result after that:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">query1.setCachePolicy(QueryCacheStrategy.LOCAL_CACHE_REFRESH);
List objects2 = context.performQuery(query1);
</pre>
</div></div>

<p>The example above shows caching with <tt>SelectQuery</tt>, but it works
exactly the same way for <tt>SQLTemplate</tt> and <tt>ProcedureQuery</tt>.
Similarly <tt>SHARED_CACHE</tt> and <tt>SHARED_CACHE_REFRESH</tt>
cache policies create cache shared by all ObjectContexts that work on top of a given DataDomain.
</p>

<h3><a name="CachingQueryResults-QueriesMappedinCayenneModeler"></a>Queries
Mapped in CayenneModeler</h3>

<p>The easiest way to set up caching is by creating a named query in CayenneModeler
with the appropriate caching type.</p>

<p><span class="image-wrap" style=""><img src="/confluence/download/attachments/10508/caching.jpg?version=2&amp;modificationDate=1139788141000"
style="border: 0px solid black" /></span></p>

<p>Then it can be executed via DataContext:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
List objects1 = context.performQuery(<span class="code-quote">"MyQuery"</span>,
<span class="code-keyword">false</span>);
</pre>
</div></div>

<p>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)</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
List objects2 = context.performQuery(<span class="code-quote">"MyQuery"</span>,
<span class="code-keyword">true</span>);
</pre>
</div></div>

<p>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.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Map parameters = Collections.singletonMap(<span class="code-quote">"key"</span>,
<span class="code-quote">"value1"</span>);
List objects1 = context.performQuery(<span class="code-quote">"MyQuery"</span>,
parameters, <span class="code-keyword">false</span>);
</pre>
</div></div>

<p>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:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Map parameters = Collections.singletonMap(<span class="code-quote">"key"</span>,
<span class="code-quote">"value2"</span>);
List objects2 = context.performQuery(<span class="code-quote">"MyQuery"</span>,
parameters, <span class="code-keyword">false</span>);
</pre>
</div></div>


    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CAYDOC/Caching+Query+Results">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=10508&revisedVersion=16&originalVersion=15">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAYDOC/Caching+Query+Results?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message