hibernate-orm/documentation/devguide/en-US/Caching.xml

584 lines
24 KiB
XML

<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "Hibernate_Development_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter>
<title>Caching</title>
<section>
<title>The query cache</title>
<para>
If you have queries that run over and over, with the same parameters, query caching provides performance gains.
</para>
<para>
Caching introduces overhead in the area of transactional processing. For example, if you cache results of a query
against an object, Hibernate needs to keep track of whether any changes have been committed against the object,
and invalidate the cache accordingly. In addition, the benefit from caching query results is limited, and highly
dependent on the usage patterns of your application. For these reasons, Hibernate disables the query cache by
default.
</para>
<procedure>
<title>Enabling the query cache</title>
<step>
<title>Set the <property>hibernate.cache.use_query_cache</property> property to <literal>true</literal>.</title>
<para>
This setting creates two new cache regions:
</para>
<itemizedlist>
<listitem>
<para>
<code>org.hibernate.cache.StandardQueryCache</code> holds the cached query results.
</para>
</listitem>
<listitem>
<para>
<code>org.hibernate.cache.UpdateTimestampsCache</code> holds timestamps of the most recent updates to
queryable tables. These timestamps validate results served from the query cache.
</para>
</listitem>
</itemizedlist>
</step>
<step>
<title>Adjust the cache timeout of the underlying cache region</title>
<para>
If you configure your underlying cache implementation to use expiry or timeouts, set the cache timeout of the
underlying cache region for the <code>UpdateTimestampsCache</code> to a higher value than the timeouts of any
of the query caches. It is possible, and recommended, to set the UpdateTimestampsCache region never to
expire. To be specific, a LRU (Least Recently Used) cache expiry policy is never appropriate.
</para>
</step>
<step>
<title>Enable results caching for specific queries</title>
<para>
Since most queries do not benefit from caching of their results, you need to enable caching for individual
queries, e ven after enabling query caching overall. To enable results caching for a particular query, call
<methodname>org.hibernate.Query.setCacheable(true)</methodname>. This call allows the query to look for
existing cache results or add its results to the cache when it is executed.
</para>
</step>
</procedure>
<para>
The query cache does not cache the state of the actual entities in the cache. It caches identifier values and
results of value type. Therefore, always use the query cache in conjunction with the second-level
cache for those entities which should be cached as part of a query result cache.
</para>
<section>
<title>Query cache regions</title>
<para>
For fine-grained control over query cache expiration policies, specify a named cache region for a particular
query by calling <methodname>Query.setCacheRegion()</methodname>.
</para>
<example>
<title>Method <methodname>setCacheRegion</methodname></title>
<programlisting language="Java" role="JAVA"><xi:include href="extras/setCacheRegion.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
</example>
<para>
To force the query cache to refresh one of its regions and disregard any cached results in the region, call
<code>org.hibernate.Query.setCacheMode(CacheMode.REFRESH)</code>. In conjunction with the region defined for the
given query, Hibernate selectively refreshes the results cached in that particular region. This is much more
efficient than bulk eviction of the region via <code>org.hibernate.SessionFactory.evictQueries()</code>.
</para>
</section>
</section>
<section>
<title>Second-level cache providers</title>
<para>
Hibernate is compatible with several second-level cache providers. None of the providers support all of
Hibernate's possible caching strategies. <xref linkend="caching-provider-table" /> lists the providers, along with
their interfaces and supported caching strategies. For definitions of caching strategies, see <xref
linkend="caching-strategies-list" />.
</para>
<section>
<title>Configuring your cache providers</title>
<para>
You can configure your cache providers using either annotations or mapping files.
</para>
<formalpara>
<title>Entities</title>
<para>
By default, entities are not part of the second-level cache, and their use is not recommended. If you
absolutely must use entities, set the <code>shared-cache-mode</code> element in
<filename>persistence.xml</filename>, or use property <property>javax.persistence.sharedCache.mode</property>
in your configuration. Use one of the values in <xref linkend="shared-cache-mode-values" />.
</para>
</formalpara>
<table id="shared-cache-mode-values">
<title>Possible values for Shared Cache Mode</title>
<tgroup cols="2">
<thead>
<row>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>ENABLE_SELECTIVE</entry>
<entry>
<para>
Entities are not cached unless you explicitly mark them as cachable. This is the default and
recommended value.
</para>
</entry>
</row>
<row>
<entry>DISABLE_SELECTIVE</entry>
<entry>
<para>
Entities are cached unless you explicitly mark them as not cacheable.
</para>
</entry>
</row>
<row>
<entry>ALL</entry>
<entry>
<para>
All entities are always cached even if you mark them as not cacheable.
</para>
</entry>
</row>
<row>
<entry>NONE</entry>
<entry>
<para>
No entities are cached even if you mark them as cacheable. This option basically disables second-level
caching.
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Set the global default cache concurrency strategy The cache concurrency strategy with the
<property>hibernate.cache.default_cache_concurrency_strategy</property> configuration property. See <xref
linkend="caching-strategies-list" /> for possible values.
</para>
<note>
<para>
When possible, define the cache concurrency strategy per entity rather than globally. Use the
<code>@org.hibernate.annotations.Cache</code> annotation.
</para>
</note>
<example id="configuring-cache-providers-annotations">
<title>Configuring cache providers using annotations</title>
<programlisting language="Java" role="JAVA"><xi:include href="extras/cache_providers_mapping.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
<para>
You can cache the content of a collection or the identifiers, if the collection contains other entities. Use
the <code>@Cache</code> annotation on the Collection property.
</para>
<para>
<code>@Cache</code> can take several attributes.
</para>
<variablelist>
<title>Attributes of <code>@Cache</code> annotation</title>
<varlistentry>
<term>usage</term>
<listitem>
<para>
The given cache concurrency strategy, which may be:
</para>
<itemizedlist>
<listitem>
<para>
<literal>NONE</literal>
</para>
</listitem>
<listitem>
<para>
<literal>READ_ONLY</literal>
</para>
</listitem>
<listitem>
<para>
<literal>NONSTRICT_READ_WRITE</literal>
</para>
</listitem>
<listitem>
<para>
<literal>READ_WRITE</literal>
</para>
</listitem>
<listitem>
<para>
<literal>TRANSACTIONAL</literal>
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>region</term>
<listitem>
<para>
The cache region. This attribute is optional, and defaults to the fully-qualified class name of the
class, or the qually-qualified role name of the collection.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>include</term>
<listitem>
<para>
Whether or not to include all properties.. Optional, and can take one of two possible values.
</para>
<itemizedlist>
<listitem>
<para>
A value of <literal>all</literal> includes all properties. This is the default.
</para>
</listitem>
<listitem>
<para>
A value of <literal>non-lazy</literal> only includes non-lazy properties.
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
</example>
<example>
<title>Configuring cache providers using mapping files</title>
<programlisting language="XML" role="XML"><xi:include href="extras/cache_providers.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
<para>
Just as in the <xref linkend="configuring-cache-providers-annotations" />, you can provide attributes in the
mapping file. There are some specific differences in the syntax for the attributes in a mapping file.
</para>
<variablelist>
<varlistentry>
<term>usage</term>
<listitem>
<para>
The caching strategy. This attribute is required, and can be any of the following values.
</para>
<itemizedlist>
<listitem><para>transactional</para></listitem>
<listitem><para>read-write</para></listitem>
<listitem><para>nonstrict-read-write</para></listitem>
<listitem><para>read-only</para></listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>region</term>
<listitem>
<para>
The name of the second-level cache region. This optional attribute defaults to the class or collection
role name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>include</term>
<listitem>
<para>
Whether properties of the entity mapped with <literal>lazy=true</literal> can be cached when
attribute-level lazy fetching is enabled. Defaults to <literal>all</literal> and can also be
<literal>non-lazy</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Instead of <code>&lt;cache&gt;</code>, you can use <code>&lt;class-cache&gt;</code> and
<code>&lt;collection-cache&gt;</code> elements in <filename>hibernate.cfg.xml</filename>.
</para>
</example>
</section>
<section id="caching-strategies-list">
<title>Caching strategies</title>
<variablelist>
<varlistentry>
<term>read-only</term>
<listitem>
<para>
A read-only cache is good for data that needs to be read often but not modified. It is simple, performs
well, and is safe to use in a clustered environment.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>nonstrict read-write</term>
<listitem>
<para>
Some applications only rarely need to modify data. This is the case if two transactions are unlikely to
try to update the same item simultaneously. In this case, you do not need strict transaction isolation,
and a nonstrict-read-write cache might be appropriate. If the cache is used in a JTA environment, you must
specify <classname>hibernate.transaction.manager_lookup_class</classname>. In other environments, ensore
that the transaction is complete before you call <methodname>Session.close()</methodname> or
<methodname>Session.disconnect()</methodname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>read-write</term>
<listitem>
<para>
A read-write cache is appropriate for an application which needs to update data regularly. Do not use a
read-write strategy if you need serializable transaction isolation. In a JTA environment, specify a
strategy for obtaining the JTA TransactionManager by setting the property
<property>hibernate.transaction.manager_lookup_class</property>. In non-JTA environments, be sure the
transaction is complete before you call <methodname>Session.close()</methodname> or
<methodname>Session.disconnect()</methodname>.
</para>
<note>
<para>
To use the read-write strategy in a clustered environment, the underlying cache implementation must
support locking. The build-in cache providers do not support locking.
</para>
</note>
</listitem>
</varlistentry>
<varlistentry>
<term>transactional</term>
<listitem>
<para>
The transactional cache strategy provides support for transactional cache providers such as JBoss
TreeCache. You can only use such a cache in a JTA environment, and you must first specify
<classname>hibernate.transaction.manager_lookup_class</classname>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="caching-provider-table">
<title>Second-level cache providers for Hibernate</title>
<informaltable>
<tgroup cols="5">
<thead>
<row>
<entry>Cache</entry>
<entry>Interface</entry>
<entry>Supported strategies</entry>
</row>
</thead>
<tbody>
<row>
<entry>HashTable (testing only)</entry>
<entry></entry>
<entry>
<itemizedlist>
<listitem><para>read-only</para></listitem>
<listitem><para>nontrict read-write</para></listitem>
<listitem><para>read-write</para></listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry>EHCache</entry>
<entry></entry>
<entry>
<itemizedlist>
<listitem><para>read-only</para></listitem>
<listitem><para>nontrict read-write</para></listitem>
<listitem><para>read-write</para></listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry>OSCache</entry>
<entry></entry>
<entry>
<itemizedlist>
<listitem><para>read-only</para></listitem>
<listitem><para>nontrict read-write</para></listitem>
<listitem><para>read-write</para></listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry>SwarmCache</entry>
<entry></entry>
<entry>
<itemizedlist>
<listitem><para>read-only</para></listitem>
<listitem><para>nontrict read-write</para></listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry>JBoss Cache 1.x</entry>
<entry></entry>
<entry>
<itemizedlist>
<listitem><para>read-only</para></listitem>
<listitem><para>transactional</para></listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry>JBoss Cache 2.x</entry>
<entry></entry>
<entry>
<itemizedlist>
<listitem><para>read-only</para></listitem>
<listitem><para>transactional</para></listitem>
</itemizedlist>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
</section>
<section>
<title>Managing the cache</title>
<section>
<title>Moving items into and out of the cache</title>
<variablelist>
<title>Actions that add an item to internal cache of the Session</title>
<varlistentry>
<term>Saving or updating an item</term>
<listitem>
<itemizedlist>
<listitem>
<para>
<methodname>save()</methodname>
</para>
</listitem>
<listitem>
<para>
<methodname>update()</methodname>
</para>
</listitem>
<listitem>
<para>
<methodname>saveOrUpdate()</methodname>
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>Retrieving an item</term>
<listitem>
<itemizedlist>
<listitem>
<para>
<methodname>load()</methodname>
</para>
</listitem>
<listitem>
<para>
<methodname>get()</methodname>
</para>
</listitem>
<listitem>
<para>
<methodname>list()</methodname>
</para>
</listitem>
<listitem>
<para>
<methodname>iterate()</methodname>
</para>
</listitem>
<listitem>
<para>
<methodname>scroll()</methodname>
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
<formalpara>
<title>Syncing or removing a cached item</title>
<para>
The state of an object is synchronized with the database when you call method
<methodname>flush()</methodname>. To avoid this synchronization, you can remove the object and all collections
from the first-level cache with the <methodname>evict()</methodname> method. To remove all items from the
Session cache, use method <methodname>Session.clear()</methodname>.
</para>
</formalpara>
<example>
<title>Evicting an item from the first-level cache</title>
<programlisting language="Java" role="JAVA"><xi:include href="extras/evicting_item.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
</example>
<formalpara>
<title>Determining whether an item belongs to the Session cache</title>
<para>
The Session provides a <methodname>contains()</methodname> method to determine if an instance belongs to the
session cache.
</para>
</formalpara>
<example>
<title>Second-level cache eviction</title>
<para>
You can evict the cached state of an instance, entire class, collection instance or entire collection role,
using methods of <classname>SessionFactory</classname>.
</para>
<programlisting language="Java" role="JAVA"><xi:include href="extras/evicting_from_second_level_cache.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
</example>
<section>
<title>Interactions between a Session and the second-level cache</title>
<para>
The CacheMode controls how a particular session interacts with the second-level cache.
</para>
<informaltable>
<tgroup cols="2">
<tbody>
<row>
<entry>CacheMode.NORMAL</entry>
<entry>reads items from and writes them to the second-level cache.</entry>
</row>
<row>
<entry>CacheMode.GET</entry>
<entry>reads items from the second-level cache, but does not write to the second-level cache except to
update data.</entry>
</row>
<row>
<entry>CacheMode.PUT</entry>
<entry>writes items to the second-level cache. It does not read from the second-level cache. It bypasses
the effect of <property>hibernate.cache.use_minimal_puts</property> and forces a refresh of the
second-level cache for all items read from the database.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
<title>Browsing the contents of a second-level or query cache region</title>
<para>
After enabling statistics, you can browse the contents of a second-level cache or query cache region.
</para>
<procedure>
<title>Enabling Statistics</title>
<step>
<para>
Set <code>hibernate.generate_statistics</code> to <literal>true</literal>.
</para>
</step>
<step>
<para>
Optionally, set <code>hibernate.cache.use_structured_entries</code> to <literal>true</literal>, to cause
Hibernate to store the cache entries in a human-readable format.
</para>
</step>
</procedure>
<example>
<title>Browsing the second-level cache entries via the Statistics API</title> <programlisting language="Java"
role="JAVA"><xi:include href="extras/browsing_cache.java" xmlns:xi="http://www.w3.org/2001/XInclude"
parse="text" /></programlisting>
</example>
</section>
</section>
</section>
</chapter>