blob: 9e4f844ece1fcb9ccc2ea82a19120fac01bda33f [file] [log] [blame]
Title: Individual Object Caching
<H2><A name="IndividualObjectCaching-IndividualObjectCaching"></A>Individual Object Caching</H2>
<P>Whenever an object is fetched from the database or created by the user and registered with Cayenne, it is automatically cached. Accessing this object later (e.g. when traversing a relationship from another object, or doing a lookup by primary key via DataObjectUtils) will not incur an overhead of extra database access. </P>
<H3><A name="IndividualObjectCaching-SynchronizingObjectsonCommit"></A>Synchronizing Objects on Commit</H3>
<P>Very often there's more than one ObjectContext working over the same Cayenne stack. E.g. in a web application each user session may have its own ObjectContext. If one of the contexts commits its changes, Cayenne automatically updates copies of each modified object across all contexts (&quot;copies&quot; mean context-specific instances of objects with the same ObjectId). So all committed object changes become immediately visible to all contexts. If there's more than one Cayenne stack running (e.g. if the application is clustered across multiple JVMs), there are ways to notify other stacks about the object changes. This can be set up in the Modeler. However full synchronization of every change often results in excessive network traffic and CPU consumption, and is usually avoided in favor of the query cache approach <A href="query-result-caching.html" title="Query Result Caching">described elsewhere</A> in this chapter.</P>
<H3><A name="IndividualObjectCaching-MemoryManagement"></A>Memory Management</H3>
<P>Cayenne ensures that the memory allocated to caching does not grow indefinitely. A cache shared between ObjectContexts has a fixed upper limit. 10000 is the default maximum number of entries, which can be changed in the Modeler. A cache attached to each ObjectContext (also referred to as &quot;local cache&quot; elsewhere in this chapter), which only stores the objects that were accessed via this context, has no upper limit. However it uses weak references to the cached <B>committed</B> objects, so they are automatically purged from cache when the application runs low on memory.</P>
<H3><A name="IndividualObjectCaching-Refreshing"></A>Refreshing</H3>
<P>Object caching happens behind the scenes, so the only case when users need to worry about object cache is when an object gets stale and needs to get refreshed. Here are the strategies for refreshing a single stale object:</P>
<UL>
<LI><EM>Perform a query to refetch one or more objects.</EM> Any of the Cayenne selecting queries would refresh previously cached objects:
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
Artist a = ...;
<SPAN class="code-comment">// <SPAN class="code-quote">&quot;a&quot;</SPAN> gets stale, we need to refresh it
</SPAN>SelectQuery query = <SPAN class="code-keyword">new</SPAN> SelectQuery(Artist.class, ...);
List&lt;Artist&gt; artists = context.performQuery(query);
<SPAN class="code-comment">// <SPAN class="code-keyword">if</SPAN> the query result includes <SPAN class="code-quote">&quot;a&quot;</SPAN>, object <SPAN class="code-quote">&quot;a&quot;</SPAN> is now refreshed</SPAN>
</PRE>
</DIV></DIV> </LI>
</UL>
<UL>
<LI><EM>Use <A href="prefetching.html" title="Prefetching">prefetching</A> to refresh to-many relationships and related objects</EM>. Cayenne selecting query would only refresh the &quot;root&quot; objects (objects of type &quot;Artist&quot; in the example above), including their &quot;simple&quot; properties and to-one relationships. To refresh to-many relationships, including to-many collection contents, and each of the related objects, a user must specify a prefetch on a given relationship. E.g.:
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
<SPAN class="code-comment">// to refresh a list of paintings attached to the Artist, use a prefetch:
</SPAN>query.addPrefetch(Artist.PAINTINGS_PROPERTY);
</PRE>
</DIV></DIV></LI>
</UL>
<UL>
<LI><EM>Use <A href="objectidquery.html" title="ObjectIdQuery">ObjectIdQuery</A> to refresh a single object.</EM> There is a special query that allows to refresh a single object - ObjectIdQuery. Specify &quot;CACHE_REFRESH&quot; caching strategy to ensure a DB fetch is performed. This requires manually creating an ObjectId:
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
ObjectId id = <SPAN class="code-keyword">new</SPAN> ObjectId(<SPAN class="code-quote">&quot;Artist&quot;</SPAN>, Artist.ID_PK_COLUMN, 5);
ObjectIdQuery query = <SPAN class="code-keyword">new</SPAN> ObjectIdQuery(id, <SPAN class="code-keyword">false</SPAN>, ObjectIdQuery.CACHE_REFRESH);
Artist a = (Artist) DataObjectUtils.objectForQuery(query);
</PRE>
</DIV></DIV></LI>
</UL>