584 lines
24 KiB
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><cache></code>, you can use <code><class-cache></code> and
|
|
<code><collection-cache></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>
|