[hibernate-commits] Hibernate SVN: r19956 - core/trunk/documentation/manual/src/main/docbook/en-US/content.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Jul 15 11:58:44 EDT 2010


Author: hardy.ferentschik
Date: 2010-07-15 11:58:43 -0400 (Thu, 15 Jul 2010)
New Revision: 19956

Modified:
   core/trunk/documentation/manual/src/main/docbook/en-US/content/performance.xml
Log:
HHH-5380 Added annotations in the cache configuration mix

Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/performance.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/performance.xml	2010-07-15 09:27:56 UTC (rev 19955)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/performance.xml	2010-07-15 15:58:43 UTC (rev 19956)
@@ -1,4 +1,4 @@
-<?xml version='1.0' encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Hibernate, Relational Persistence for Idiomatic Java
   ~
@@ -22,150 +22,128 @@
   ~ 51 Franklin Street, Fifth Floor
   ~ Boston, MA  02110-1301  USA
   -->
-
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!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_-_Relational_Persistence_for_Idiomatic_Java.ent">
 %BOOK_ENTITIES;
-
 ]>
-
 <chapter id="performance">
-    <title>Improving performance</title>
+  <title>Improving performance</title>
 
-    <section id="performance-fetching" revision="2">
-        <title>Fetching strategies</title>
+  <section id="performance-fetching" revision="2">
+    <title>Fetching strategies</title>
 
-        <para>
-            Hibernate uses a <emphasis>fetching strategy</emphasis> to
-            retrieve associated objects if the application needs to navigate the association. 
-            Fetch strategies can be declared in the O/R mapping metadata, or over-ridden by a 
-            particular HQL or <literal>Criteria</literal> query.
-        </para>
+    <para>Hibernate uses a <emphasis>fetching strategy</emphasis> to retrieve
+    associated objects if the application needs to navigate the association.
+    Fetch strategies can be declared in the O/R mapping metadata, or
+    over-ridden by a particular HQL or <literal>Criteria</literal>
+    query.</para>
 
-        <para>
-            Hibernate3 defines the following fetching strategies:
-        </para>
+    <para>Hibernate3 defines the following fetching strategies:</para>
 
-        <itemizedlist>
-             <listitem>
-                <para>
-                    <emphasis>Join fetching</emphasis>: Hibernate retrieves the
-                    associated instance or collection in the same <literal>SELECT</literal>,
-                    using an <literal>OUTER JOIN</literal>.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>Select fetching</emphasis>: a second <literal>SELECT</literal>
-                    is used to retrieve the associated entity or collection. Unless
-                    you explicitly disable lazy fetching by specifying <literal>lazy="false"</literal>, 
-                    this second select will only be executed when you access the
-                    association.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>Subselect fetching</emphasis>: a second <literal>SELECT</literal>
-                    is used to retrieve the associated collections for all entities retrieved in a
-                    previous query or fetch. Unless you explicitly disable lazy fetching by specifying 
-                    <literal>lazy="false"</literal>, this second select will only be executed when you 
-                    access the association.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>Batch fetching</emphasis>: an optimization strategy
-                    for select fetching. Hibernate retrieves a batch of entity instances 
-                    or collections in a single <literal>SELECT</literal> by specifying 
-                    a list of primary or foreign keys.
-                </para>
-            </listitem>
-        </itemizedlist>
-        
-        <para>
-            Hibernate also distinguishes between:
-        </para>
+    <itemizedlist>
+      <listitem>
+        <para><emphasis>Join fetching</emphasis>: Hibernate retrieves the
+        associated instance or collection in the same
+        <literal>SELECT</literal>, using an <literal>OUTER
+        JOIN</literal>.</para>
+      </listitem>
 
-        <itemizedlist>
-             <listitem>
-                <para>
-                    <emphasis>Immediate fetching</emphasis>: an association, collection or
-                    attribute is fetched immediately when the owner is loaded.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>Lazy collection fetching</emphasis>: a collection is fetched 
-                    when the application invokes an operation upon that collection. This
-                    is the default for collections.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>"Extra-lazy" collection fetching</emphasis>: individual
-                    elements of the collection are accessed from the database as needed.
-                    Hibernate tries not to fetch the whole collection into memory unless
-                    absolutely needed. It is suitable for large collections.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>Proxy fetching</emphasis>: a single-valued association is 
-                    fetched when a method other than the identifier getter is invoked
-                    upon the associated object.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>"No-proxy" fetching</emphasis>: a single-valued association is 
-                    fetched when the instance variable is accessed. Compared to proxy fetching, 
-                    this approach is less lazy; the association is fetched even when only the 
-                    identifier is accessed.  It is also more transparent, since no proxy is visible to 
-                    the application. This approach requires buildtime bytecode instrumentation 
-                    and is rarely necessary.
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <emphasis>Lazy attribute fetching</emphasis>: an attribute or single
-                    valued association is fetched when the instance variable is accessed. 
-                    This approach requires buildtime bytecode instrumentation and is rarely 
-                    necessary.
-                </para>
-            </listitem>
-        </itemizedlist>
-        
-        <para>
-            We have two orthogonal notions here: <emphasis>when</emphasis> is the association
-            fetched and <emphasis>how</emphasis> is it fetched. It is important that you do not
-            confuse them. We use <literal>fetch</literal> to tune performance. We can use 
-            <literal>lazy</literal> to define a contract for what data is always available 
-            in any detached instance of a particular class.
-        </para>
- 
-        <section id="performance-fetching-lazy">
-            <title>Working with lazy associations</title>
-            
-            <para>
-                By default, Hibernate3 uses lazy select fetching for collections and lazy proxy
-                fetching for single-valued associations. These defaults make sense for most
-                associations in the majority of applications. 
-            </para>
-            
-            <para>
-                If you set 
-                <literal>hibernate.default_batch_fetch_size</literal>, Hibernate will use the 
-                batch fetch optimization for lazy fetching. This optimization can also be enabled 
-                at a more granular level.
-            </para>
-            
-            <para>
-                Please be aware that access to a 
-                lazy association outside of the context of an open Hibernate session will result 
-                in an exception. For example:
-            </para>
-        
-            <programlisting role="JAVA"><![CDATA[s = sessions.openSession();
+      <listitem>
+        <para><emphasis>Select fetching</emphasis>: a second
+        <literal>SELECT</literal> is used to retrieve the associated entity or
+        collection. Unless you explicitly disable lazy fetching by specifying
+        <literal>lazy="false"</literal>, this second select will only be
+        executed when you access the association.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>Subselect fetching</emphasis>: a second
+        <literal>SELECT</literal> is used to retrieve the associated
+        collections for all entities retrieved in a previous query or fetch.
+        Unless you explicitly disable lazy fetching by specifying
+        <literal>lazy="false"</literal>, this second select will only be
+        executed when you access the association.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>Batch fetching</emphasis>: an optimization strategy
+        for select fetching. Hibernate retrieves a batch of entity instances
+        or collections in a single <literal>SELECT</literal> by specifying a
+        list of primary or foreign keys.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Hibernate also distinguishes between:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para><emphasis>Immediate fetching</emphasis>: an association,
+        collection or attribute is fetched immediately when the owner is
+        loaded.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>Lazy collection fetching</emphasis>: a collection is
+        fetched when the application invokes an operation upon that
+        collection. This is the default for collections.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>"Extra-lazy" collection fetching</emphasis>:
+        individual elements of the collection are accessed from the database
+        as needed. Hibernate tries not to fetch the whole collection into
+        memory unless absolutely needed. It is suitable for large
+        collections.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>Proxy fetching</emphasis>: a single-valued association
+        is fetched when a method other than the identifier getter is invoked
+        upon the associated object.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>"No-proxy" fetching</emphasis>: a single-valued
+        association is fetched when the instance variable is accessed.
+        Compared to proxy fetching, this approach is less lazy; the
+        association is fetched even when only the identifier is accessed. It
+        is also more transparent, since no proxy is visible to the
+        application. This approach requires buildtime bytecode instrumentation
+        and is rarely necessary.</para>
+      </listitem>
+
+      <listitem>
+        <para><emphasis>Lazy attribute fetching</emphasis>: an attribute or
+        single valued association is fetched when the instance variable is
+        accessed. This approach requires buildtime bytecode instrumentation
+        and is rarely necessary.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>We have two orthogonal notions here: <emphasis>when</emphasis> is
+    the association fetched and <emphasis>how</emphasis> is it fetched. It is
+    important that you do not confuse them. We use <literal>fetch</literal> to
+    tune performance. We can use <literal>lazy</literal> to define a contract
+    for what data is always available in any detached instance of a particular
+    class.</para>
+
+    <section id="performance-fetching-lazy">
+      <title>Working with lazy associations</title>
+
+      <para>By default, Hibernate3 uses lazy select fetching for collections
+      and lazy proxy fetching for single-valued associations. These defaults
+      make sense for most associations in the majority of applications.</para>
+
+      <para>If you set <literal>hibernate.default_batch_fetch_size</literal>,
+      Hibernate will use the batch fetch optimization for lazy fetching. This
+      optimization can also be enabled at a more granular level.</para>
+
+      <para>Please be aware that access to a lazy association outside of the
+      context of an open Hibernate session will result in an exception. For
+      example:</para>
+
+      <programlisting role="JAVA">s = sessions.openSession();
 Transaction tx = s.beginTransaction();
             
 User u = (User) s.createQuery("from User u where u.name=:userName")
@@ -175,1260 +153,1383 @@
 tx.commit();
 s.close();
 
-Integer accessLevel = (Integer) permissions.get("accounts");  // Error!]]></programlisting>
+Integer accessLevel = (Integer) permissions.get("accounts");  // Error!</programlisting>
 
-            <para>
-                Since the permissions collection was not initialized when the 
-                <literal>Session</literal> was closed, the collection will not be able to 
-                load its state. <emphasis>Hibernate does not support lazy initialization 
-                for detached objects</emphasis>. This can be fixed by moving the code that reads 
-                from the collection to just before the transaction is committed.
-            </para>
-    
-            <para>
-                Alternatively, you can use a non-lazy collection or association, 
-                by specifying <literal>lazy="false"</literal> for the association mapping.
-                However, it is intended that lazy initialization be used for almost all 
-                collections and associations. If you define too many non-lazy associations 
-                in your object model, Hibernate will fetch the entire 
-                database into memory in every transaction.
-            </para>
-    
-            <para>
-                On the other hand, you can use join fetching, which is non-lazy by 
-                nature, instead of select fetching in a particular transaction. We will now explain
-                how to customize the fetching strategy. In Hibernate3, the mechanisms for
-                choosing a fetch strategy are identical for single-valued associations and
-                collections.
-            </para>
-        
-        </section>
-        
-        <section id="performance-fetching-custom" revision="4">
-            <title>Tuning fetch strategies</title>
-            
-            <para>
-                Select fetching (the default) is extremely vulnerable to N+1 selects problems, 
-                so we might want to enable join fetching in the mapping document:
-            </para>
-            
-            <programlisting role="XML"><![CDATA[<set name="permissions"
-            fetch="join">
-    <key column="userId"/>
-    <one-to-many class="Permission"/>
-</set]]></programlisting>
+      <para>Since the permissions collection was not initialized when the
+      <literal>Session</literal> was closed, the collection will not be able
+      to load its state. <emphasis>Hibernate does not support lazy
+      initialization for detached objects</emphasis>. This can be fixed by
+      moving the code that reads from the collection to just before the
+      transaction is committed.</para>
 
-           <programlisting role="XML"><![CDATA[<many-to-one name="mother" class="Cat" fetch="join"/>]]></programlisting>
+      <para>Alternatively, you can use a non-lazy collection or association,
+      by specifying <literal>lazy="false"</literal> for the association
+      mapping. However, it is intended that lazy initialization be used for
+      almost all collections and associations. If you define too many non-lazy
+      associations in your object model, Hibernate will fetch the entire
+      database into memory in every transaction.</para>
 
-            <para>
-                The <literal>fetch</literal> strategy defined in the mapping document affects:
-            </para>
-            
-        <itemizedlist>
-             <listitem>
-                <para>
-                    retrieval via <literal>get()</literal> or <literal>load()</literal>
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    retrieval that happens implicitly when an association is navigated
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    <literal>Criteria</literal> queries
-                </para>
-            </listitem>
-            <listitem>
-                <para>
-                    HQL queries if <literal>subselect</literal> fetching is used
-                </para>
-            </listitem>
-        </itemizedlist>
+      <para>On the other hand, you can use join fetching, which is non-lazy by
+      nature, instead of select fetching in a particular transaction. We will
+      now explain how to customize the fetching strategy. In Hibernate3, the
+      mechanisms for choosing a fetch strategy are identical for single-valued
+      associations and collections.</para>
+    </section>
 
-            <para>
-                Irrespective of the fetching strategy you use, the defined non-lazy graph is guaranteed
-                to be loaded into memory. This might, however, result in several immediate selects
-                being used to execute a particular HQL query.
-            </para>
+    <section id="performance-fetching-custom" revision="4">
+      <title>Tuning fetch strategies</title>
 
-            <para>
-                Usually, the mapping document is not used to customize fetching. Instead, we
-                keep the default behavior, and override it for a particular transaction, using 
-                <literal>left join fetch</literal> in HQL. This tells Hibernate to fetch 
-                the association eagerly in the first select, using an outer join. In the
-                <literal>Criteria</literal> query API, you would use
-                <literal>setFetchMode(FetchMode.JOIN)</literal>.
-            </para>
-            
-            <para>
-                If you want to change the fetching strategy used by
-                <literal>get()</literal> or <literal>load()</literal>, you can use a 
-                <literal>Criteria</literal> query. For example:
-            </para>
-            
-            <programlisting role="JAVA"><![CDATA[User user = (User) session.createCriteria(User.class)
+      <para>Select fetching (the default) is extremely vulnerable to N+1
+      selects problems, so we might want to enable join fetching in the
+      mapping document:</para>
+
+      <programlisting role="XML">&lt;set name="permissions"
+            fetch="join"&gt;
+    &lt;key column="userId"/&gt;
+    &lt;one-to-many class="Permission"/&gt;
+&lt;/set</programlisting>
+
+      <programlisting role="XML">&lt;many-to-one name="mother" class="Cat" fetch="join"/&gt;</programlisting>
+
+      <para>The <literal>fetch</literal> strategy defined in the mapping
+      document affects:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>retrieval via <literal>get()</literal> or
+          <literal>load()</literal></para>
+        </listitem>
+
+        <listitem>
+          <para>retrieval that happens implicitly when an association is
+          navigated</para>
+        </listitem>
+
+        <listitem>
+          <para><literal>Criteria</literal> queries</para>
+        </listitem>
+
+        <listitem>
+          <para>HQL queries if <literal>subselect</literal> fetching is
+          used</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Irrespective of the fetching strategy you use, the defined
+      non-lazy graph is guaranteed to be loaded into memory. This might,
+      however, result in several immediate selects being used to execute a
+      particular HQL query.</para>
+
+      <para>Usually, the mapping document is not used to customize fetching.
+      Instead, we keep the default behavior, and override it for a particular
+      transaction, using <literal>left join fetch</literal> in HQL. This tells
+      Hibernate to fetch the association eagerly in the first select, using an
+      outer join. In the <literal>Criteria</literal> query API, you would use
+      <literal>setFetchMode(FetchMode.JOIN)</literal>.</para>
+
+      <para>If you want to change the fetching strategy used by
+      <literal>get()</literal> or <literal>load()</literal>, you can use a
+      <literal>Criteria</literal> query. For example:</para>
+
+      <programlisting role="JAVA">User user = (User) session.createCriteria(User.class)
                 .setFetchMode("permissions", FetchMode.JOIN)
                 .add( Restrictions.idEq(userId) )
-                .uniqueResult();]]></programlisting>
-                
-            <para>
-                This is Hibernate's equivalent of what some ORM solutions call a "fetch plan".
-            </para>
+                .uniqueResult();</programlisting>
 
-            <para>
-                A completely different approach to problems with N+1 selects is to use the 
-                second-level cache.
-            </para>
+      <para>This is Hibernate's equivalent of what some ORM solutions call a
+      "fetch plan".</para>
 
-        </section>
+      <para>A completely different approach to problems with N+1 selects is to
+      use the second-level cache.</para>
+    </section>
 
-        <section id="performance-fetching-proxies" revision="2">
-            <title>Single-ended association proxies</title>
+    <section id="performance-fetching-proxies" revision="2">
+      <title>Single-ended association proxies</title>
 
-            <para>
-                Lazy fetching for collections is implemented using Hibernate's own implementation
-                of persistent collections. However, a different mechanism is needed for lazy
-                behavior in single-ended associations. The target entity of the association must
-                be proxied. Hibernate implements lazy initializing proxies for persistent objects
-                using runtime bytecode enhancement which is accessed via the CGLIB library.
-            </para>
+      <para>Lazy fetching for collections is implemented using Hibernate's own
+      implementation of persistent collections. However, a different mechanism
+      is needed for lazy behavior in single-ended associations. The target
+      entity of the association must be proxied. Hibernate implements lazy
+      initializing proxies for persistent objects using runtime bytecode
+      enhancement which is accessed via the CGLIB library.</para>
 
-            <para>
-                At startup, Hibernate3 generates proxies by default for all persistent classes
-                and uses them to enable lazy fetching of <literal>many-to-one</literal> and
-                <literal>one-to-one</literal> associations.
-            </para>
+      <para>At startup, Hibernate3 generates proxies by default for all
+      persistent classes and uses them to enable lazy fetching of
+      <literal>many-to-one</literal> and <literal>one-to-one</literal>
+      associations.</para>
 
-            <para>
-                The mapping file may declare an interface to use as the proxy interface for that
-                class, with the <literal>proxy</literal> attribute. By default, Hibernate uses a subclass
-                of the class. <emphasis>The proxied class must implement a default constructor
-                with at least package visibility. This constructor is recommended for all persistent classes</emphasis>.
-            </para>
+      <para>The mapping file may declare an interface to use as the proxy
+      interface for that class, with the <literal>proxy</literal> attribute.
+      By default, Hibernate uses a subclass of the class. <emphasis>The
+      proxied class must implement a default constructor with at least package
+      visibility. This constructor is recommended for all persistent
+      classes</emphasis>.</para>
 
-            <para>
-                There are potential problems to note when extending this approach to polymorphic classes.For example:
-            </para>
+      <para>There are potential problems to note when extending this approach
+      to polymorphic classes.For example:</para>
 
-            <programlisting role="XML"><![CDATA[<class name="Cat" proxy="Cat">
+      <programlisting role="XML">&lt;class name="Cat" proxy="Cat"&gt;
     ......
-    <subclass name="DomesticCat">
+    &lt;subclass name="DomesticCat"&gt;
         .....
-    </subclass>
-</class>]]></programlisting>
+    &lt;/subclass&gt;
+&lt;/class&gt;</programlisting>
 
-            <para>
-                Firstly, instances of <literal>Cat</literal> will never be castable to
-                <literal>DomesticCat</literal>, even if the underlying instance is an
-                instance of <literal>DomesticCat</literal>:
-            </para>
+      <para>Firstly, instances of <literal>Cat</literal> will never be
+      castable to <literal>DomesticCat</literal>, even if the underlying
+      instance is an instance of <literal>DomesticCat</literal>:</para>
 
-            <programlisting role="JAVA"><![CDATA[Cat cat = (Cat) session.load(Cat.class, id);  // instantiate a proxy (does not hit the db)
+      <programlisting role="JAVA">Cat cat = (Cat) session.load(Cat.class, id);  // instantiate a proxy (does not hit the db)
 if ( cat.isDomesticCat() ) {                  // hit the db to initialize the proxy
     DomesticCat dc = (DomesticCat) cat;       // Error!
     ....
-}]]></programlisting>
+}</programlisting>
 
-            <para>
-                Secondly, it is possible to break proxy <literal>==</literal>:
-            </para>
+      <para>Secondly, it is possible to break proxy
+      <literal>==</literal>:</para>
 
-            <programlisting role="JAVA"><![CDATA[Cat cat = (Cat) session.load(Cat.class, id);            // instantiate a Cat proxy
+      <programlisting role="JAVA">Cat cat = (Cat) session.load(Cat.class, id);            // instantiate a Cat proxy
 DomesticCat dc = 
         (DomesticCat) session.load(DomesticCat.class, id);  // acquire new DomesticCat proxy!
-System.out.println(cat==dc);                            // false]]></programlisting>
+System.out.println(cat==dc);                            // false</programlisting>
 
-            <para>
-                However, the situation is not quite as bad as it looks. Even though we now have two references
-                to different proxy objects, the underlying instance will still be the same object:
-            </para>
+      <para>However, the situation is not quite as bad as it looks. Even
+      though we now have two references to different proxy objects, the
+      underlying instance will still be the same object:</para>
 
-            <programlisting role="JAVA"><![CDATA[cat.setWeight(11.0);  // hit the db to initialize the proxy
-System.out.println( dc.getWeight() );  // 11.0]]></programlisting>
+      <programlisting role="JAVA">cat.setWeight(11.0);  // hit the db to initialize the proxy
+System.out.println( dc.getWeight() );  // 11.0</programlisting>
 
-            <para>
-                Third, you cannot use a CGLIB proxy for a <literal>final</literal> class or a class
-                with any <literal>final</literal> methods.
-            </para>
+      <para>Third, you cannot use a CGLIB proxy for a <literal>final</literal>
+      class or a class with any <literal>final</literal> methods.</para>
 
-            <para>
-                Finally, if your persistent object acquires any resources upon instantiation (e.g. in
-                initializers or default constructor), then those resources will also be acquired by
-                the proxy. The proxy class is an actual subclass of the persistent class.
-            </para>
+      <para>Finally, if your persistent object acquires any resources upon
+      instantiation (e.g. in initializers or default constructor), then those
+      resources will also be acquired by the proxy. The proxy class is an
+      actual subclass of the persistent class.</para>
 
-            <para>
-                These problems are all due to fundamental limitations in Java's single inheritance model.
-                To avoid these problems your persistent classes must each implement an interface
-                that declares its business methods. You should specify these interfaces in the mapping file where 
-		<literal>CatImpl</literal> implements the interface <literal>Cat</literal> and <literal>DomesticCatImpl</literal>
-	        implements the interface <literal>DomesticCat</literal>. For example: 
-            </para>
+      <para>These problems are all due to fundamental limitations in Java's
+      single inheritance model. To avoid these problems your persistent
+      classes must each implement an interface that declares its business
+      methods. You should specify these interfaces in the mapping file where
+      <literal>CatImpl</literal> implements the interface
+      <literal>Cat</literal> and <literal>DomesticCatImpl</literal> implements
+      the interface <literal>DomesticCat</literal>. For example:</para>
 
-            <programlisting role="XML"><![CDATA[<class name="CatImpl" proxy="Cat">
+      <programlisting role="XML">&lt;class name="CatImpl" proxy="Cat"&gt;
     ......
-    <subclass name="DomesticCatImpl" proxy="DomesticCat">
+    &lt;subclass name="DomesticCatImpl" proxy="DomesticCat"&gt;
         .....
-    </subclass>
-</class>]]></programlisting>
+    &lt;/subclass&gt;
+&lt;/class&gt;</programlisting>
 
-            <para>
-                Then proxies for instances of <literal>Cat</literal> and <literal>DomesticCat</literal> can be returned
-                by <literal>load()</literal> or <literal>iterate()</literal>. 
-            </para>
+      <para>Then proxies for instances of <literal>Cat</literal> and
+      <literal>DomesticCat</literal> can be returned by
+      <literal>load()</literal> or <literal>iterate()</literal>.</para>
 
-            <programlisting role="JAVA"><![CDATA[Cat cat = (Cat) session.load(CatImpl.class, catid);
+      <programlisting role="JAVA">Cat cat = (Cat) session.load(CatImpl.class, catid);
 Iterator iter = session.createQuery("from CatImpl as cat where cat.name='fritz'").iterate();
-Cat fritz = (Cat) iter.next();]]></programlisting>
+Cat fritz = (Cat) iter.next();</programlisting>
 
-            
-	    <note><title>Note</title>
-	    <para>
-		<literal>list()</literal> does not usually return proxies.
-	    </para>
-	    </note>
-	    
-	     <para>
-                Relationships are also lazily initialized. This means you must declare any properties to be of
-                type <literal>Cat</literal>, not <literal>CatImpl</literal>.
-            </para>
+      <note>
+        <title>Note</title>
 
-            <para>
-                Certain operations do <emphasis>not</emphasis> require proxy initialization:
-            </para>
+        <para><literal>list()</literal> does not usually return
+        proxies.</para>
+      </note>
 
-            <itemizedlist spacing="compact">
-                <listitem>
-                    <para>
-                        <literal>equals()</literal>: if the persistent class does not override
-                        <literal>equals()</literal>
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        <literal>hashCode()</literal>: if the persistent class does not override
-                        <literal>hashCode()</literal>
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        The identifier getter method
-                    </para>
-                </listitem>
-            </itemizedlist>
+      <para>Relationships are also lazily initialized. This means you must
+      declare any properties to be of type <literal>Cat</literal>, not
+      <literal>CatImpl</literal>.</para>
 
-            <para>
-                Hibernate will detect persistent classes that override <literal>equals()</literal> or
-                <literal>hashCode()</literal>.
-            </para>
-            
-            <para>
-                By choosing <literal>lazy="no-proxy"</literal> instead of the default 
-                <literal>lazy="proxy"</literal>, you can avoid problems associated with typecasting.
-                However, buildtime bytecode instrumentation is required, and all operations
-                will result in immediate proxy initialization.
-            </para>
+      <para>Certain operations do <emphasis>not</emphasis> require proxy
+      initialization:</para>
 
-        </section>
+      <itemizedlist spacing="compact">
+        <listitem>
+          <para><literal>equals()</literal>: if the persistent class does not
+          override <literal>equals()</literal></para>
+        </listitem>
 
-        <section id="performance-fetching-initialization" revision="1">
-            <title>Initializing collections and proxies</title>
+        <listitem>
+          <para><literal>hashCode()</literal>: if the persistent class does
+          not override <literal>hashCode()</literal></para>
+        </listitem>
 
-            <para>
-                A <literal>LazyInitializationException</literal> will be thrown by Hibernate if an uninitialized 
-                collection or proxy is accessed outside of the scope of the <literal>Session</literal>, i.e., when 
-                the entity owning the collection or having the reference to the proxy is in the detached state.
-            </para>
+        <listitem>
+          <para>The identifier getter method</para>
+        </listitem>
+      </itemizedlist>
 
-            <para>
-                Sometimes a proxy or collection needs to be initialized before closing the
-                <literal>Session</literal>. You can force initialization by calling
-                <literal>cat.getSex()</literal> or <literal>cat.getKittens().size()</literal>, for example.
-                However, this can be confusing to readers of the code and it is not convenient for generic code.
-            </para>
+      <para>Hibernate will detect persistent classes that override
+      <literal>equals()</literal> or <literal>hashCode()</literal>.</para>
 
-            <para>
-                The static methods <literal>Hibernate.initialize()</literal> and <literal>Hibernate.isInitialized()</literal>,
-                provide the application with a convenient way of working with lazily initialized collections or
-                proxies. <literal>Hibernate.initialize(cat)</literal> will force the initialization of a proxy,
-                <literal>cat</literal>, as long as its <literal>Session</literal> is still open.
-                <literal>Hibernate.initialize( cat.getKittens() )</literal> has a similar effect for the collection
-                of kittens.
-            </para>
+      <para>By choosing <literal>lazy="no-proxy"</literal> instead of the
+      default <literal>lazy="proxy"</literal>, you can avoid problems
+      associated with typecasting. However, buildtime bytecode instrumentation
+      is required, and all operations will result in immediate proxy
+      initialization.</para>
+    </section>
 
-            <para>
-                Another option is to keep the <literal>Session</literal> open until all required
-                collections and proxies have been loaded. In some application architectures,
-                particularly where the code that accesses data using Hibernate, and the code that
-                uses it are in different application layers or different physical processes, it 
-                can be a problem to ensure that the <literal>Session</literal> is open when a 
-                collection is initialized. There are two basic ways to deal with this issue:
-            </para>
+    <section id="performance-fetching-initialization" revision="1">
+      <title>Initializing collections and proxies</title>
 
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        In a web-based application, a servlet filter can be used to close the
-                        <literal>Session</literal> only at the end of a user request, once
-                        the rendering of the view is complete (the <emphasis>Open Session in
-                        View</emphasis> pattern).  Of course, this places heavy demands on the 
-                        correctness of the exception handling of your application infrastructure. 
-                        It is vitally important that the <literal>Session</literal> is closed and the 
-                        transaction ended before returning to the user, even when an exception occurs 
-                        during rendering of the view. See the Hibernate Wiki for examples of this
-                        "Open Session in View" pattern.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        In an application with a separate business tier, the business logic must
-                        "prepare" all collections that the web tier needs before
-                        returning. This means that the business tier should load all the data and
-                        return all the data already initialized to the presentation/web tier that
-                        is required for a particular use case. Usually, the application calls
-                        <literal>Hibernate.initialize()</literal> for each collection that will
-                        be needed in the web tier (this call must occur before the session is closed)
-                        or retrieves the collection eagerly using a Hibernate query with a
-                        <literal>FETCH</literal> clause or a <literal>FetchMode.JOIN</literal> in
-                        <literal>Criteria</literal>. This is usually easier if you adopt the
-                        <emphasis>Command</emphasis> pattern instead of a <emphasis>Session Facade</emphasis>.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        You can also attach a previously loaded object to a new <literal>Session</literal>
-                        with <literal>merge()</literal> or <literal>lock()</literal> before
-                        accessing uninitialized collections or other proxies. Hibernate does not,
-                        and certainly <emphasis>should</emphasis> not, do this automatically since it 
-                        would introduce impromptu transaction semantics.
-                    </para>
-                </listitem>
-            </itemizedlist>
+      <para>A <literal>LazyInitializationException</literal> will be thrown by
+      Hibernate if an uninitialized collection or proxy is accessed outside of
+      the scope of the <literal>Session</literal>, i.e., when the entity
+      owning the collection or having the reference to the proxy is in the
+      detached state.</para>
 
-            <para>
-                Sometimes you do not want to initialize a large collection, but still need some
-                information about it, like its size, for example, or a subset of the data.
-            </para>
+      <para>Sometimes a proxy or collection needs to be initialized before
+      closing the <literal>Session</literal>. You can force initialization by
+      calling <literal>cat.getSex()</literal> or
+      <literal>cat.getKittens().size()</literal>, for example. However, this
+      can be confusing to readers of the code and it is not convenient for
+      generic code.</para>
 
-            <para>
-                You can use a collection filter to get the size of a collection without initializing it:
-            </para>
+      <para>The static methods <literal>Hibernate.initialize()</literal> and
+      <literal>Hibernate.isInitialized()</literal>, provide the application
+      with a convenient way of working with lazily initialized collections or
+      proxies. <literal>Hibernate.initialize(cat)</literal> will force the
+      initialization of a proxy, <literal>cat</literal>, as long as its
+      <literal>Session</literal> is still open. <literal>Hibernate.initialize(
+      cat.getKittens() )</literal> has a similar effect for the collection of
+      kittens.</para>
 
-            <programlisting role="JAVA"><![CDATA[( (Integer) s.createFilter( collection, "select count(*)" ).list().get(0) ).intValue()]]></programlisting>
+      <para>Another option is to keep the <literal>Session</literal> open
+      until all required collections and proxies have been loaded. In some
+      application architectures, particularly where the code that accesses
+      data using Hibernate, and the code that uses it are in different
+      application layers or different physical processes, it can be a problem
+      to ensure that the <literal>Session</literal> is open when a collection
+      is initialized. There are two basic ways to deal with this issue:</para>
 
-            <para>
-                The <literal>createFilter()</literal> method is also used to efficiently retrieve subsets
-                of a collection without needing to initialize the whole collection:
-            </para>
+      <itemizedlist>
+        <listitem>
+          <para>In a web-based application, a servlet filter can be used to
+          close the <literal>Session</literal> only at the end of a user
+          request, once the rendering of the view is complete (the
+          <emphasis>Open Session in View</emphasis> pattern). Of course, this
+          places heavy demands on the correctness of the exception handling of
+          your application infrastructure. It is vitally important that the
+          <literal>Session</literal> is closed and the transaction ended
+          before returning to the user, even when an exception occurs during
+          rendering of the view. See the Hibernate Wiki for examples of this
+          "Open Session in View" pattern.</para>
+        </listitem>
 
-            <programlisting role="JAVA"><![CDATA[s.createFilter( lazyCollection, "").setFirstResult(0).setMaxResults(10).list();]]></programlisting>
+        <listitem>
+          <para>In an application with a separate business tier, the business
+          logic must "prepare" all collections that the web tier needs before
+          returning. This means that the business tier should load all the
+          data and return all the data already initialized to the
+          presentation/web tier that is required for a particular use case.
+          Usually, the application calls
+          <literal>Hibernate.initialize()</literal> for each collection that
+          will be needed in the web tier (this call must occur before the
+          session is closed) or retrieves the collection eagerly using a
+          Hibernate query with a <literal>FETCH</literal> clause or a
+          <literal>FetchMode.JOIN</literal> in <literal>Criteria</literal>.
+          This is usually easier if you adopt the <emphasis>Command</emphasis>
+          pattern instead of a <emphasis>Session Facade</emphasis>.</para>
+        </listitem>
 
-        </section>
+        <listitem>
+          <para>You can also attach a previously loaded object to a new
+          <literal>Session</literal> with <literal>merge()</literal> or
+          <literal>lock()</literal> before accessing uninitialized collections
+          or other proxies. Hibernate does not, and certainly
+          <emphasis>should</emphasis> not, do this automatically since it
+          would introduce impromptu transaction semantics.</para>
+        </listitem>
+      </itemizedlist>
 
-        <section id="performance-fetching-batch">
-            <title>Using batch fetching</title>
+      <para>Sometimes you do not want to initialize a large collection, but
+      still need some information about it, like its size, for example, or a
+      subset of the data.</para>
 
-            <para>
-                Using batch fetching, Hibernate can load several uninitialized
-                proxies if one proxy is accessed. Batch fetching is an optimization of the lazy select
-                fetching strategy. There are two ways you can configure batch fetching: on the class level and the collection level.
-            </para>
+      <para>You can use a collection filter to get the size of a collection
+      without initializing it:</para>
 
-            <para>
-                Batch fetching for classes/entities is easier to understand. Consider the following example:
-                at runtime you have 25 <literal>Cat</literal> instances loaded in a <literal>Session</literal>, and each
-                <literal>Cat</literal> has a reference to its <literal>owner</literal>, a <literal>Person</literal>.
-                The <literal>Person</literal> class is mapped with a proxy, <literal>lazy="true"</literal>. If you now
-                iterate through all cats and call <literal>getOwner()</literal> on each, Hibernate will, by default,
-                execute 25 <literal>SELECT</literal> statements to retrieve the proxied owners. You can tune this
-                behavior by specifying a <literal>batch-size</literal> in the mapping of <literal>Person</literal>:
-            </para>
+      <programlisting role="JAVA">( (Integer) s.createFilter( collection, "select count(*)" ).list().get(0) ).intValue()</programlisting>
 
-            <programlisting role="XML"><![CDATA[<class name="Person" batch-size="10">...</class>]]></programlisting>
+      <para>The <literal>createFilter()</literal> method is also used to
+      efficiently retrieve subsets of a collection without needing to
+      initialize the whole collection:</para>
 
-            <para>
-                Hibernate will now execute only three queries: the pattern is 10, 10, 5.
-            </para>
+      <programlisting role="JAVA">s.createFilter( lazyCollection, "").setFirstResult(0).setMaxResults(10).list();</programlisting>
+    </section>
 
-            <para>
-                You can also enable batch fetching of collections. For example, if each <literal>Person</literal> has
-                a lazy collection of <literal>Cat</literal>s, and 10 persons are currently loaded in the
-                <literal>Session</literal>, iterating through all persons will generate 10 <literal>SELECT</literal>s,
-                one for every call to <literal>getCats()</literal>. If you enable batch fetching for the
-                <literal>cats</literal> collection in the mapping of <literal>Person</literal>, Hibernate can pre-fetch
-                collections:
-            </para>
+    <section id="performance-fetching-batch">
+      <title>Using batch fetching</title>
 
-            <programlisting role="XML"><![CDATA[<class name="Person">
-    <set name="cats" batch-size="3">
+      <para>Using batch fetching, Hibernate can load several uninitialized
+      proxies if one proxy is accessed. Batch fetching is an optimization of
+      the lazy select fetching strategy. There are two ways you can configure
+      batch fetching: on the class level and the collection level.</para>
+
+      <para>Batch fetching for classes/entities is easier to understand.
+      Consider the following example: at runtime you have 25
+      <literal>Cat</literal> instances loaded in a <literal>Session</literal>,
+      and each <literal>Cat</literal> has a reference to its
+      <literal>owner</literal>, a <literal>Person</literal>. The
+      <literal>Person</literal> class is mapped with a proxy,
+      <literal>lazy="true"</literal>. If you now iterate through all cats and
+      call <literal>getOwner()</literal> on each, Hibernate will, by default,
+      execute 25 <literal>SELECT</literal> statements to retrieve the proxied
+      owners. You can tune this behavior by specifying a
+      <literal>batch-size</literal> in the mapping of
+      <literal>Person</literal>:</para>
+
+      <programlisting role="XML">&lt;class name="Person" batch-size="10"&gt;...&lt;/class&gt;</programlisting>
+
+      <para>Hibernate will now execute only three queries: the pattern is 10,
+      10, 5.</para>
+
+      <para>You can also enable batch fetching of collections. For example, if
+      each <literal>Person</literal> has a lazy collection of
+      <literal>Cat</literal>s, and 10 persons are currently loaded in the
+      <literal>Session</literal>, iterating through all persons will generate
+      10 <literal>SELECT</literal>s, one for every call to
+      <literal>getCats()</literal>. If you enable batch fetching for the
+      <literal>cats</literal> collection in the mapping of
+      <literal>Person</literal>, Hibernate can pre-fetch collections:</para>
+
+      <programlisting role="XML">&lt;class name="Person"&gt;
+    &lt;set name="cats" batch-size="3"&gt;
         ...
-    </set>
-</class>]]></programlisting>
+    &lt;/set&gt;
+&lt;/class&gt;</programlisting>
 
-            <para>
-                With a <literal>batch-size</literal> of 3, Hibernate will load 3, 3, 3, 1 collections in four
-                <literal>SELECT</literal>s. Again, the value of the attribute depends on the expected number of
-                uninitialized collections in a particular <literal>Session</literal>.
-            </para>
+      <para>With a <literal>batch-size</literal> of 3, Hibernate will load 3,
+      3, 3, 1 collections in four <literal>SELECT</literal>s. Again, the value
+      of the attribute depends on the expected number of uninitialized
+      collections in a particular <literal>Session</literal>.</para>
 
-            <para>
-                Batch fetching of collections is particularly useful if you have a nested tree of items, i.e.
-                the typical bill-of-materials pattern. However, a <emphasis>nested set</emphasis> or a
-                <emphasis>materialized path</emphasis> might be a better option for read-mostly trees.
-            </para>
+      <para>Batch fetching of collections is particularly useful if you have a
+      nested tree of items, i.e. the typical bill-of-materials pattern.
+      However, a <emphasis>nested set</emphasis> or a <emphasis>materialized
+      path</emphasis> might be a better option for read-mostly trees.</para>
+    </section>
 
-        </section>
+    <section id="performance-fetching-subselect">
+      <title>Using subselect fetching</title>
 
-        <section id="performance-fetching-subselect">
-            <title>Using subselect fetching</title>
+      <para>If one lazy collection or single-valued proxy has to be fetched,
+      Hibernate will load all of them, re-running the original query in a
+      subselect. This works in the same way as batch-fetching but without the
+      piecemeal loading.</para>
 
-            <para>
-                If one lazy collection or single-valued proxy has to be fetched, Hibernate will load all of
-                them, re-running the original query in a subselect. This works in the same way as
-                batch-fetching but without the piecemeal loading.
-            </para>
-            
-            <!-- TODO: Write more about this -->
+      <!-- TODO: Write more about this -->
+    </section>
 
-        </section>
+    <section id="performance-fetching-profiles">
+      <title>Fetch profiles</title>
 
-        <section id="performance-fetching-profiles">
-            <title>Fetch profiles</title>
+      <para>Another way to affect the fetching strategy for loading associated
+      objects is through something called a fetch profile, which is a named
+      configuration associated with the
+      <interfacename>org.hibernate.SessionFactory</interfacename> but enabled,
+      by name, on the <interfacename>org.hibernate.Session</interfacename>.
+      Once enabled on a <interfacename>org.hibernate.Session</interfacename>,
+      the fetch profile wull be in affect for that
+      <interfacename>org.hibernate.Session</interfacename> until it is
+      explicitly disabled.</para>
 
-            <para>
-                Another way to affect the fetching strategy for loading associated objects is through something
-                called a fetch profile, which is a named configuration associated with the
-                <interfacename>org.hibernate.SessionFactory</interfacename> but enabled, by name, on the
-                <interfacename>org.hibernate.Session</interfacename>.  Once enabled on a
-                <interfacename>org.hibernate.Session</interfacename>, the fetch profile wull be in affect for
-                that <interfacename>org.hibernate.Session</interfacename> until it is explicitly disabled.
-            </para>
-            <para>
-                So what does that mean?  Well lets explain that by way of an example.  Say we have
-                the following mappings:
-            </para>
-            <programlisting role="XML"><![CDATA[<hibernate-mapping>
-    <class name="Customer">
+      <para>So what does that mean? Well lets explain that by way of an
+      example. Say we have the following mappings:</para>
+
+      <programlisting role="XML">&lt;hibernate-mapping&gt;
+    &lt;class name="Customer"&gt;
         ...
-        <set name="orders" inverse="true">
-            <key column="cust_id"/>
-            <one-to-many class="Order"/>
-        </set>
-    </class>
-    <class name="Order">
+        &lt;set name="orders" inverse="true"&gt;
+            &lt;key column="cust_id"/&gt;
+            &lt;one-to-many class="Order"/&gt;
+        &lt;/set&gt;
+    &lt;/class&gt;
+    &lt;class name="Order"&gt;
         ...
-    </class>
-</hibernate-mapping>]]></programlisting>
-            <para>
-                Now normally when you get a reference to a particular customer, that customer's set of
-                orders will be lazy meaning we will not yet have loaded those orders from the database.
-                Normally this is a good thing.  Now lets say that you have a certain use case where
-                it is more efficient to load the customer and their orders together.  One way certainly is
-                to use "dynamic fetching" strategies via an HQL or criteria queries.  But another option is
-                to use a fetch profile to achieve that.  Just add the following to your mapping:
-            </para>
-            <programlisting role="XML"><![CDATA[<hibernate-mapping>
+    &lt;/class&gt;
+&lt;/hibernate-mapping&gt;</programlisting>
+
+      <para>Now normally when you get a reference to a particular customer,
+      that customer's set of orders will be lazy meaning we will not yet have
+      loaded those orders from the database. Normally this is a good thing.
+      Now lets say that you have a certain use case where it is more efficient
+      to load the customer and their orders together. One way certainly is to
+      use "dynamic fetching" strategies via an HQL or criteria queries. But
+      another option is to use a fetch profile to achieve that. Just add the
+      following to your mapping:</para>
+
+      <programlisting role="XML">&lt;hibernate-mapping&gt;
     ...
-    <fetch-profile name="customer-with-orders">
-        <fetch entity="Customer" association="orders" style="join"/>
-    </fetch-profile>
-</hibernate-mapping>]]></programlisting>
-            <para>
-                or even:
-            </para>
-            <programlisting role="XML"><![CDATA[<hibernate-mapping>
-    <class name="Customer">
+    &lt;fetch-profile name="customer-with-orders"&gt;
+        &lt;fetch entity="Customer" association="orders" style="join"/&gt;
+    &lt;/fetch-profile&gt;
+&lt;/hibernate-mapping&gt;</programlisting>
+
+      <para>or even:</para>
+
+      <programlisting role="XML">&lt;hibernate-mapping&gt;
+    &lt;class name="Customer"&gt;
         ...
-        <fetch-profile name="customer-with-orders">
-            <fetch association="orders" style="join"/>
-        </fetch-profile>
-    </class>
+        &lt;fetch-profile name="customer-with-orders"&gt;
+            &lt;fetch association="orders" style="join"/&gt;
+        &lt;/fetch-profile&gt;
+    &lt;/class&gt;
     ...
-</hibernate-mapping>]]></programlisting>
-            <para>
-                Now the following code will actually load both the customer <emphasis>and their orders</emphasis>:
-            </para>
-            <programlisting role="JAVA"><![CDATA[
+&lt;/hibernate-mapping&gt;</programlisting>
+
+      <para>Now the following code will actually load both the customer
+      <emphasis>and their orders</emphasis>:</para>
+
+      <programlisting role="JAVA">
     Session session = ...;
     session.enableFetchProfile( "customer-with-orders" );  // name matches from mapping
     Customer customer = (Customer) session.get( Customer.class, customerId );
 
-]]></programlisting>
-            <para>
-                Currently only join style fetch profiles are supported, but they plan is to support additional
-                styles.  See <ulink url="http://opensource.atlassian.com/projects/hibernate/browse/HHH-3414">HHH-3414</ulink>
-                for details.
-            </para>
-        </section>
+</programlisting>
 
-        <section id="performance-fetching-lazyproperties">
-            <title>Using lazy property fetching</title>
+      <para>Currently only join style fetch profiles are supported, but they
+      plan is to support additional styles. See <ulink
+      url="http://opensource.atlassian.com/projects/hibernate/browse/HHH-3414">HHH-3414</ulink>
+      for details.</para>
+    </section>
 
-            <para>
-                Hibernate3 supports the lazy fetching of individual properties. This optimization technique
-                is also known as <emphasis>fetch groups</emphasis>. Please note that this is mostly a
-                marketing feature; optimizing row reads is much more important than
-                optimization of column reads. However, only loading some properties of a class could
-                be useful in extreme cases. For example, when legacy tables have hundreds of columns and the data model
-                cannot be improved.
-            </para>
+    <section id="performance-fetching-lazyproperties">
+      <title>Using lazy property fetching</title>
 
-            <para>
-                To enable lazy property loading, set the <literal>lazy</literal> attribute on your
-                particular property mappings:
-            </para>
+      <para>Hibernate3 supports the lazy fetching of individual properties.
+      This optimization technique is also known as <emphasis>fetch
+      groups</emphasis>. Please note that this is mostly a marketing feature;
+      optimizing row reads is much more important than optimization of column
+      reads. However, only loading some properties of a class could be useful
+      in extreme cases. For example, when legacy tables have hundreds of
+      columns and the data model cannot be improved.</para>
 
-            <programlisting role="XML"><![CDATA[<class name="Document">
-       <id name="id">
-        <generator class="native"/>
-    </id>
-    <property name="name" not-null="true" length="50"/>
-    <property name="summary" not-null="true" length="200" lazy="true"/>
-    <property name="text" not-null="true" length="2000" lazy="true"/>
-</class>]]></programlisting>
+      <para>To enable lazy property loading, set the <literal>lazy</literal>
+      attribute on your particular property mappings:</para>
 
-            <para>
-                Lazy property loading requires buildtime bytecode instrumentation. If your persistent
-                classes are not enhanced, Hibernate will ignore lazy property settings and
-                return to immediate fetching.
-            </para>
+      <programlisting role="XML">&lt;class name="Document"&gt;
+       &lt;id name="id"&gt;
+        &lt;generator class="native"/&gt;
+    &lt;/id&gt;
+    &lt;property name="name" not-null="true" length="50"/&gt;
+    &lt;property name="summary" not-null="true" length="200" lazy="true"/&gt;
+    &lt;property name="text" not-null="true" length="2000" lazy="true"/&gt;
+&lt;/class&gt;</programlisting>
 
-            <para>
-                For bytecode instrumentation, use the following Ant task:
-            </para>
+      <para>Lazy property loading requires buildtime bytecode instrumentation.
+      If your persistent classes are not enhanced, Hibernate will ignore lazy
+      property settings and return to immediate fetching.</para>
 
-            <programlisting role="XML"><![CDATA[<target name="instrument" depends="compile">
-    <taskdef name="instrument" classname="org.hibernate.tool.instrument.InstrumentTask">
-        <classpath path="${jar.path}"/>
-        <classpath path="${classes.dir}"/>
-        <classpath refid="lib.class.path"/>
-    </taskdef>
+      <para>For bytecode instrumentation, use the following Ant task:</para>
 
-    <instrument verbose="true">
-        <fileset dir="${testclasses.dir}/org/hibernate/auction/model">
-            <include name="*.class"/>
-        </fileset>
-    </instrument>
-</target>]]></programlisting>
+      <programlisting role="XML">&lt;target name="instrument" depends="compile"&gt;
+    &lt;taskdef name="instrument" classname="org.hibernate.tool.instrument.InstrumentTask"&gt;
+        &lt;classpath path="${jar.path}"/&gt;
+        &lt;classpath path="${classes.dir}"/&gt;
+        &lt;classpath refid="lib.class.path"/&gt;
+    &lt;/taskdef&gt;
 
-            <para>
-                A different way of avoiding unnecessary column reads, at least for
-                read-only transactions, is to use the projection features of HQL or Criteria
-                queries. This avoids the need for buildtime bytecode processing and is
-                certainly a preferred solution.
-            </para>
-            
-            <para>
-                You can force the usual eager fetching of properties using <literal>fetch all
-                properties</literal> in HQL.
-            </para>
+    &lt;instrument verbose="true"&gt;
+        &lt;fileset dir="${testclasses.dir}/org/hibernate/auction/model"&gt;
+            &lt;include name="*.class"/&gt;
+        &lt;/fileset&gt;
+    &lt;/instrument&gt;
+&lt;/target&gt;</programlisting>
 
-        </section>
+      <para>A different way of avoiding unnecessary column reads, at least for
+      read-only transactions, is to use the projection features of HQL or
+      Criteria queries. This avoids the need for buildtime bytecode processing
+      and is certainly a preferred solution.</para>
+
+      <para>You can force the usual eager fetching of properties using
+      <literal>fetch all properties</literal> in HQL.</para>
     </section>
+  </section>
 
-    <section id="performance-cache" revision="1">
-        <title>The Second Level Cache</title>
+  <section id="performance-cache" revision="1">
+    <title>The Second Level Cache</title>
 
-        <para>
-            A Hibernate <literal>Session</literal> is a transaction-level cache of persistent data. It is
-            possible to configure a cluster or JVM-level (<literal>SessionFactory</literal>-level) cache on 
-            a class-by-class and collection-by-collection basis. You can even plug in a clustered cache. Be 
-            aware that caches are not aware of changes made to the persistent store by another application. 
-            They can, however, be configured to regularly expire cached data.
-        </para>
-        
-        <para revision="1">
-            You have the option to tell Hibernate which caching implementation to use by
-            specifying the name of a class that implements <literal>org.hibernate.cache.CacheProvider</literal>
-            using the property <literal>hibernate.cache.provider_class</literal>.  Hibernate
-            is bundled with a number of built-in integrations with the open-source cache providers
-            that are listed below. You can also implement your own and plug it in as
-            outlined above. Note that versions prior to 3.2 use EhCache as the default
-            cache provider.
-        </para>
+    <para>A Hibernate <literal>Session</literal> is a transaction-level cache
+    of persistent data. It is possible to configure a cluster or JVM-level
+    (<literal>SessionFactory</literal>-level) cache on a class-by-class and
+    collection-by-collection basis. You can even plug in a clustered cache. Be
+    aware that caches are not aware of changes made to the persistent store by
+    another application. They can, however, be configured to regularly expire
+    cached data.</para>
 
-        <table frame="topbot" id="cacheproviders" revision="1">
-            <title>Cache Providers</title>
-            <tgroup cols='5' align='left' colsep='1' rowsep='1'>
-            <colspec colname='c1' colwidth="1*"/>
-            <colspec colname='c2' colwidth="3*"/>
-            <colspec colname='c3' colwidth="1*"/>
-            <colspec colname='c4' colwidth="1*"/>
-            <colspec colname='c5' colwidth="1*"/>
-            <thead>
+    <para revision="1">You have the option to tell Hibernate which caching
+    implementation to use by specifying the name of a class that implements
+    <literal>org.hibernate.cache.CacheProvider</literal> using the property
+    <literal>hibernate.cache.provider_class</literal>. Hibernate is bundled
+    with a number of built-in integrations with the open-source cache
+    providers that are listed in <xref linkend="cacheproviders" />. You can
+    also implement your own and plug it in as outlined above. Note that
+    versions prior to Hibernate 3.2 use EhCache as the default cache
+    provider.</para>
+
+    <table frame="topbot" id="cacheproviders" revision="1">
+      <title>Cache Providers</title>
+
+      <tgroup align="left" cols="5" colsep="1" rowsep="1">
+        <colspec colname="c1" colwidth="1*" />
+
+        <colspec colname="c2" colwidth="3*" />
+
+        <colspec colname="c3" colwidth="1*" />
+
+        <colspec colname="c4" colwidth="1*" />
+
+        <colspec colname="c5" colwidth="1*" />
+
+        <thead>
+          <row>
+            <entry>Cache</entry>
+
+            <entry>Provider class</entry>
+
+            <entry>Type</entry>
+
+            <entry>Cluster Safe</entry>
+
+            <entry>Query Cache Supported</entry>
+          </row>
+        </thead>
+
+        <tbody>
+          <row>
+            <entry>Hashtable (not intended for production use)</entry>
+
+            <entry><literal>org.hibernate.cache.HashtableCacheProvider</literal></entry>
+
+            <entry>memory</entry>
+
+            <entry></entry>
+
+            <entry>yes</entry>
+          </row>
+
+          <row>
+            <entry>EHCache</entry>
+
+            <entry><literal>org.hibernate.cache.EhCacheProvider</literal></entry>
+
+            <entry>memory, disk</entry>
+
+            <entry></entry>
+
+            <entry>yes</entry>
+          </row>
+
+          <row>
+            <entry>OSCache</entry>
+
+            <entry><literal>org.hibernate.cache.OSCacheProvider</literal></entry>
+
+            <entry>memory, disk</entry>
+
+            <entry></entry>
+
+            <entry>yes</entry>
+          </row>
+
+          <row>
+            <entry>SwarmCache</entry>
+
+            <entry><literal>org.hibernate.cache.SwarmCacheProvider</literal></entry>
+
+            <entry>clustered (ip multicast)</entry>
+
+            <entry>yes (clustered invalidation)</entry>
+
+            <entry></entry>
+          </row>
+
+          <row>
+            <entry>JBoss Cache 1.x</entry>
+
+            <entry><literal>org.hibernate.cache.TreeCacheProvider</literal></entry>
+
+            <entry>clustered (ip multicast), transactional</entry>
+
+            <entry>yes (replication)</entry>
+
+            <entry>yes (clock sync req.)</entry>
+          </row>
+
+          <row>
+            <entry>JBoss Cache 2</entry>
+
+            <entry><literal>org.hibernate.cache.jbc.JBossCacheRegionFactory</literal></entry>
+
+            <entry>clustered (ip multicast), transactional</entry>
+
+            <entry>yes (replication or invalidation)</entry>
+
+            <entry>yes (clock sync req.)</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+
+    <section id="performance-cache-mapping" revision="2">
+      <title>Cache mappings</title>
+
+      <para>As we have done in previous chapters we are looking at the two
+      different possibiltites to configure caching. First configuration via
+      annotations and then via Hibernate mapping files.</para>
+
+      <para>By default, entities are not part of the second level cache and we
+      recommend you to stick to this setting. However, you can override this
+      by setting the <literal>shared-cache-mode</literal> element in your
+      <filename>persistence.xml</filename> file or by using the
+      <literal>javax.persistence.sharedCache.mode </literal>property in your
+      configuration. The following values are possible:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><literal>ENABLE_SELECTIVE</literal> (Default and recommended
+          value): entities are not cached unless explicitly marked as
+          cacheable.</para>
+        </listitem>
+
+        <listitem>
+          <para><literal>DISABLE_SELECTIVE</literal>: entities are cached
+          unless explicitly marked as not cacheable.</para>
+        </listitem>
+
+        <listitem>
+          <para><literal>ALL</literal>: all entities are always cached even if
+          marked as non cacheable.</para>
+        </listitem>
+
+        <listitem>
+          <para><literal>NONE</literal>: no entity are cached even if marked
+          as cacheable. This option can make sense to disable second-level
+          cache altogether.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>The cache concurrency strategy used by default can be set globaly
+      via the
+      <literal>hibernate.cache.default_cache_concurrency_strategy</literal>
+      configuration property. The values for this property are:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><literal>read-only</literal></para>
+        </listitem>
+
+        <listitem>
+          <para><literal>read-write</literal></para>
+        </listitem>
+
+        <listitem>
+          <para><literal>nonstrict-read-write</literal></para>
+        </listitem>
+
+        <listitem>
+          <para><literal>transactional</literal></para>
+        </listitem>
+      </itemizedlist>
+
+      <note>
+        <para>It is recommended to define the cache concurrency strategy per
+        entity rather than using a global one. Use the
+        <classname>@org.hibernate.annotations.Cache</classname> annotation for
+        that.</para>
+      </note>
+
+      <example id="example-cache-concurrency-with-cache-annotation">
+        <title>Definition of cache concurrency strategy via
+        <classname>@Cache</classname></title>
+
+        <programlisting language="JAVA" role="JAVA">@Entity 
+ at Cacheable
+ at Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public class Forest { ... }</programlisting>
+      </example>
+
+      <para>Hibernate also let's you cache the content of a collection or the
+      identifiers if the collection contains other entities. Use the
+      <classname>@Cache</classname> annotation on the collection
+      property.</para>
+
+      <example>
+        <title>Caching collections using annotations</title>
+
+        <programlisting language="JAVA" role="JAVA">@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+ at JoinColumn(name="CUST_ID")
+ at Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public SortedSet&lt;Ticket&gt; getTickets() {
+    return tickets;
+}</programlisting>
+      </example>
+
+      <para><xref linkend="example-cache-annotation-with-attributes" />shows
+      the<literal> @org.hibernate.annotations.Cache</literal> annotations with
+      its attributes. It allows you to define the caching strategy and region
+      of a given second level cache.</para>
+
+      <example id="example-cache-annotation-with-attributes">
+        <title><classname>@Cache</classname> annotation with
+        attributes</title>
+
+        <programlistingco>
+          <areaspec>
+            <area coords="2" id="cache-hm1" />
+
+            <area coords="3" id="cache-hm2" />
+
+            <area coords="4" id="cache-hm3" />
+          </areaspec>
+
+          <programlisting>@Cache(
+    CacheConcurrencyStrategy usage();
+    String region() default "";
+    String include() default "all";
+)</programlisting>
+
+          <calloutlist>
+            <callout arearefs="cache-hm1">
+              <para>usage: the given cache concurrency strategy (NONE,
+              READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE,
+              TRANSACTIONAL)</para>
+            </callout>
+
+            <callout arearefs="cache-hm2">
+              <para>region (optional): the cache region (default to the fqcn
+              of the class or the fq role name of the collection)</para>
+            </callout>
+
+            <callout arearefs="cache-hm3">
+              <para><literal>include</literal> (optional): all to include all
+              properties, non-lazy to only include non lazy properties
+              (default all).</para>
+            </callout>
+          </calloutlist>
+        </programlistingco>
+      </example>
+
+      <para>Let's now take a look at Hibernate mapping files. There the
+      <literal>&lt;cache&gt;</literal> element of a class or collection
+      mapping is used to configure the second level cache. Looking at <xref
+      linkend="example-hibernate-cache-mapping-element" /> the parallels to
+      anotations is obvious.</para>
+
+      <example id="example-hibernate-cache-mapping-element">
+        <title>The Hibernate <literal>&lt;cache&gt;</literal> mapping
+        element</title>
+
+        <programlistingco>
+          <areaspec>
+            <area coords="2" id="cache1" />
+
+            <area coords="3" id="cache2" />
+
+            <area coords="4" id="cache3" />
+          </areaspec>
+
+          <programlisting>&lt;cache
+    usage="transactional|read-write|nonstrict-read-write|read-only"
+    region="RegionName"
+    include="all|non-lazy"
+/&gt;</programlisting>
+
+          <calloutlist>
+            <callout arearefs="cache1">
+              <para><literal>usage</literal> (required) specifies the caching
+              strategy: <literal>transactional</literal>,
+              <literal>read-write</literal>,
+              <literal>nonstrict-read-write</literal> or
+              <literal>read-only</literal></para>
+            </callout>
+
+            <callout arearefs="cache2">
+              <para><literal>region</literal> (optional: defaults to the class
+              or collection role name): specifies the name of the second level
+              cache region</para>
+            </callout>
+
+            <callout arearefs="cache3">
+              <para><literal>include</literal> (optional: defaults to
+              <literal>all</literal>) <literal>non-lazy</literal>: specifies
+              that properties of the entity mapped with
+              <literal>lazy="true"</literal> cannot be cached when
+              attribute-level lazy fetching is enabled</para>
+            </callout>
+          </calloutlist>
+        </programlistingco>
+      </example>
+
+      <para>Alternatively to <literal>&lt;cache&gt;</literal>, you can use
+      <literal>&lt;class-cache&gt;</literal> and
+      <literal>&lt;collection-cache&gt;</literal> elements in
+      <literal>hibernate.cfg.xml</literal>.</para>
+
+      <para>Let's now have a closer look at the different usage
+      strategies</para>
+    </section>
+
+    <section id="performance-cache-readonly">
+      <title>Strategy: read only</title>
+
+      <para>If your application needs to read, but not modify, instances of a
+      persistent class, a <literal>read-only</literal> cache can be used. This
+      is the simplest and optimal performing strategy. It is even safe for use
+      in a cluster.</para>
+    </section>
+
+    <section id="performance-cache-readwrite">
+      <title>Strategy: read/write</title>
+
+      <para>If the application needs to update data, a
+      <literal>read-write</literal> cache might be appropriate. This cache
+      strategy should never be used if serializable transaction isolation
+      level is required. If the cache is used in a JTA environment, you must
+      specify the property
+      <literal>hibernate.transaction.manager_lookup_class</literal> and naming
+      a strategy for obtaining the JTA <literal>TransactionManager</literal>.
+      In other environments, you should ensure that the transaction is
+      completed when <literal>Session.close()</literal> or
+      <literal>Session.disconnect()</literal> is called. If you want to use
+      this strategy in a cluster, you should ensure that the underlying cache
+      implementation supports locking. The built-in cache providers
+      <emphasis>do not</emphasis> support locking.</para>
+    </section>
+
+    <section id="performance-cache-nonstrict">
+      <title>Strategy: nonstrict read/write</title>
+
+      <para>If the application only occasionally needs to update data (i.e. if
+      it is extremely unlikely that two transactions would try to update the
+      same item simultaneously), and strict transaction isolation is not
+      required, a <literal>nonstrict-read-write</literal> cache might be
+      appropriate. If the cache is used in a JTA environment, you must specify
+      <literal>hibernate.transaction.manager_lookup_class</literal>. In other
+      environments, you should ensure that the transaction is completed when
+      <literal>Session.close()</literal> or
+      <literal>Session.disconnect()</literal> is called.</para>
+    </section>
+
+    <section id="performance-cache-transactional">
+      <title>Strategy: transactional</title>
+
+      <para>The <literal>transactional</literal> cache strategy provides
+      support for fully transactional cache providers such as JBoss TreeCache.
+      Such a cache can only be used in a JTA environment and you must specify
+      <literal>hibernate.transaction.manager_lookup_class</literal>.</para>
+    </section>
+
+    <section id="performance-cache-compat-matrix">
+      <title>Cache-provider/concurrency-strategy compatibility</title>
+
+      <important>
+        <para>None of the cache providers support all of the cache concurrency
+        strategies.</para>
+      </important>
+
+      <para>The following table shows which providers are compatible with
+      which concurrency strategies.</para>
+
+      <table frame="topbot">
+        <title>Cache Concurrency Strategy Support</title>
+
+        <tgroup align="left" cols="5" colsep="1" rowsep="1">
+          <colspec colname="c1" colwidth="1*" />
+
+          <colspec colname="c2" colwidth="1*" />
+
+          <colspec colname="c3" colwidth="1*" />
+
+          <colspec colname="c4" colwidth="1*" />
+
+          <colspec colname="c5" colwidth="1*" />
+
+          <thead>
             <row>
               <entry>Cache</entry>
-              <entry>Provider class</entry>
-              <entry>Type</entry>
-              <entry>Cluster Safe</entry>
-              <entry>Query Cache Supported</entry>
+
+              <entry>read-only</entry>
+
+              <entry>nonstrict-read-write</entry>
+
+              <entry>read-write</entry>
+
+              <entry>transactional</entry>
             </row>
-            </thead>
-            <tbody>
+          </thead>
+
+          <tbody>
             <row>
-                <entry>Hashtable (not intended for production use)</entry>
-                <entry><literal>org.hibernate.cache.HashtableCacheProvider</literal></entry>
-                <entry>memory</entry>
-                <entry> </entry>
-                <entry>yes</entry>
+              <entry>Hashtable (not intended for production use)</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry></entry>
             </row>
+
             <row>
-                <entry>EHCache</entry>
-                <entry><literal>org.hibernate.cache.EhCacheProvider</literal></entry>
-                <entry>memory, disk</entry>
-                <entry> </entry>
-                <entry>yes</entry>
+              <entry>EHCache</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry></entry>
             </row>
+
             <row>
-                <entry>OSCache</entry>
-                <entry><literal>org.hibernate.cache.OSCacheProvider</literal></entry>
-                <entry>memory, disk</entry>
-                <entry> </entry>
-                <entry>yes</entry>
+              <entry>OSCache</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry></entry>
             </row>
+
             <row>
-                <entry>SwarmCache</entry>
-                <entry><literal>org.hibernate.cache.SwarmCacheProvider</literal></entry>
-                <entry>clustered (ip multicast)</entry>
-                <entry>yes (clustered invalidation)</entry>
-                <entry> </entry>
+              <entry>SwarmCache</entry>
+
+              <entry>yes</entry>
+
+              <entry>yes</entry>
+
+              <entry></entry>
+
+              <entry></entry>
             </row>
+
             <row>
-                <entry>JBoss Cache 1.x</entry>
-                <entry><literal>org.hibernate.cache.TreeCacheProvider</literal></entry>
-                <entry>clustered (ip multicast), transactional</entry>
-                <entry>yes (replication)</entry>
-                <entry>yes (clock sync req.)</entry>
+              <entry>JBoss Cache 1.x</entry>
+
+              <entry>yes</entry>
+
+              <entry></entry>
+
+              <entry></entry>
+
+              <entry>yes</entry>
             </row>
+
             <row>
-                <entry>JBoss Cache 2</entry>
-                <entry><literal>org.hibernate.cache.jbc.JBossCacheRegionFactory</literal></entry>
-                <entry>clustered (ip multicast), transactional</entry>
-                <entry>yes (replication or invalidation)</entry>
-                <entry>yes (clock sync req.)</entry>
+              <entry>JBoss Cache 2</entry>
+
+              <entry>yes</entry>
+
+              <entry></entry>
+
+              <entry></entry>
+
+              <entry>yes</entry>
             </row>
-            </tbody>
-            </tgroup>
-        </table>
+          </tbody>
+        </tgroup>
+      </table>
+    </section>
+  </section>
 
-        <section id="performance-cache-mapping" revision="2">
-            <title>Cache mappings</title>
+  <section id="performance-sessioncache" revision="2">
+    <title>Managing the caches</title>
 
-            <para>
-                The <literal>&lt;cache&gt;</literal> element of a class or collection mapping has the
-                following form:
-            </para>
+    <para>Whenever you pass an object to <literal>save()</literal>,
+    <literal>update()</literal> or <literal>saveOrUpdate()</literal>, and
+    whenever you retrieve an object using <literal>load()</literal>,
+    <literal>get()</literal>, <literal>list()</literal>,
+    <literal>iterate()</literal> or <literal>scroll()</literal>, that object
+    is added to the internal cache of the <literal>Session</literal>.</para>
 
-            <programlistingco>
-                <areaspec>
-                    <area id="cache1" coords="2"/>
-                    <area id="cache2" coords="3"/>
-                    <area id="cache3" coords="4"/>
-                </areaspec>
-                <programlisting><![CDATA[<cache
-    usage="transactional|read-write|nonstrict-read-write|read-only"
-    region="RegionName"
-    include="all|non-lazy"
-/>]]></programlisting>
-                <calloutlist>
-                    <callout arearefs="cache1">
-                        <para>
-                            <literal>usage</literal> (required) specifies the caching strategy:
-                            <literal>transactional</literal>,
-                            <literal>read-write</literal>,
-                            <literal>nonstrict-read-write</literal> or
-                            <literal>read-only</literal>
-                        </para>
-                    </callout>                   
-                    <callout arearefs="cache2">
-                        <para>
-                            <literal>region</literal> (optional: defaults to the class or
-                            collection role name): specifies the name of the second level cache 
-                            region
-                        </para>
-                    </callout>                   
-                    <callout arearefs="cache3">
-                        <para>
-                            <literal>include</literal> (optional: defaults to <literal>all</literal>) 
-                            <literal>non-lazy</literal>: specifies that properties of the entity mapped
-                            with <literal>lazy="true"</literal> cannot be cached when attribute-level
-                            lazy fetching is enabled
-                        </para>
-                    </callout>                   
-                </calloutlist>
-            </programlistingco>
-            
-            <para>
-                Alternatively, you can specify <literal>&lt;class-cache&gt;</literal> and 
-                <literal>&lt;collection-cache&gt;</literal> elements in <literal>hibernate.cfg.xml</literal>.
-            </para>
-            
-            <para>
-                The <literal>usage</literal> attribute specifies a <emphasis>cache concurrency strategy</emphasis>.
-            </para>
+    <para>When <literal>flush()</literal> is subsequently called, the state of
+    that object will be synchronized with the database. If you do not want
+    this synchronization to occur, or if you are processing a huge number of
+    objects and need to manage memory efficiently, the
+    <literal>evict()</literal> method can be used to remove the object and its
+    collections from the first-level cache.</para>
 
-        </section>
+    <example>
+      <title>Explcitly evicting a cached instance from the first level cache
+      using <methodname>Session.evict()</methodname></title>
 
-        <section id="performance-cache-readonly">
-            <title>Strategy: read only</title>
+      <programlisting role="JAVA">ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //a huge result set
+while ( cats.next() ) {
+    Cat cat = (Cat) cats.get(0);
+    doSomethingWithACat(cat);
+    sess.evict(cat);
+}</programlisting>
+    </example>
 
-            <para>
-                If your application needs to read, but not modify, instances of a persistent class, a 
-                <literal>read-only</literal> cache can be used. This is the simplest and optimal performing
-                strategy. It is even safe for use in a cluster.
-            </para>
+    <para>The <literal>Session</literal> also provides a
+    <literal>contains()</literal> method to determine if an instance belongs
+    to the session cache.</para>
 
-            <programlisting role="XML"><![CDATA[<class name="eg.Immutable" mutable="false">
-    <cache usage="read-only"/>
-    ....
-</class>]]></programlisting>
+    <para>To evict all objects from the session cache, call
+    <literal>Session.clear()</literal></para>
 
-        </section>
+    <para>For the second-level cache, there are methods defined on
+    <literal>SessionFactory</literal> for evicting the cached state of an
+    instance, entire class, collection instance or entire collection
+    role.</para>
 
+    <example>
+      <title>Second-level cache eviction via
+      <methodname>SessionFactoty.evict() </methodname>and
+      <methodname>SessionFacyory.evictCollection()</methodname></title>
 
-        <section id="performance-cache-readwrite">
-            <title>Strategy: read/write</title>
+      <programlisting role="JAVA">sessionFactory.evict(Cat.class, catId); //evict a particular Cat
+sessionFactory.evict(Cat.class);  //evict all Cats
+sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
+sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections</programlisting>
+    </example>
 
-            <para>
-                If the application needs to update data, a <literal>read-write</literal> cache might be appropriate. 
-                This cache strategy should never be used if serializable transaction isolation level is required. 
-                If the cache is used in a JTA environment, you must specify the property 
-                <literal>hibernate.transaction.manager_lookup_class</literal> and naming a strategy for obtaining the 
-                JTA <literal>TransactionManager</literal>. In other environments, you should ensure that the transaction 
-                is completed when <literal>Session.close()</literal> or <literal>Session.disconnect()</literal> is called. 
-                If you want to use this strategy in a cluster, you should ensure that the underlying cache implementation 
-                supports locking. The built-in cache providers <emphasis>do not</emphasis> support locking.
-            </para>
+    <para>The <literal>CacheMode</literal> controls how a particular session
+    interacts with the second-level cache:</para>
 
-            <programlisting role="XML"><![CDATA[<class name="eg.Cat" .... >
-    <cache usage="read-write"/>
-    ....
-    <set name="kittens" ... >
-        <cache usage="read-write"/>
-        ....
-    </set>
-</class>]]></programlisting>
+    <itemizedlist>
+      <listitem>
+        <para><literal>CacheMode.NORMAL</literal>: will read items from and
+        write items to the second-level cache</para>
+      </listitem>
 
-        </section>
+      <listitem>
+        <para><literal>CacheMode.GET</literal>: will read items from the
+        second-level cache. Do not write to the second-level cache except when
+        updating data</para>
+      </listitem>
 
-        <section id="performance-cache-nonstrict">
-            <title>Strategy: nonstrict read/write</title>
+      <listitem>
+        <para><literal>CacheMode.PUT</literal>: will write items to the
+        second-level cache. Do not read from the second-level cache</para>
+      </listitem>
 
-            <para>
-                If the application only occasionally needs to update data (i.e. if it is extremely unlikely that two 
-                transactions would try to update the same item simultaneously), and strict transaction isolation is
-                not required, a <literal>nonstrict-read-write</literal> cache might be appropriate. If the cache is 
-                used in a JTA environment, you must specify <literal>hibernate.transaction.manager_lookup_class</literal>. 
-                In other environments, you should ensure that the transaction is completed when 
-                <literal>Session.close()</literal> or <literal>Session.disconnect()</literal> is called.
-            </para>
+      <listitem>
+        <para><literal>CacheMode.REFRESH</literal>: will write items to the
+        second-level cache. Do not read from the second-level cache. Bypass
+        the effect of <literal>hibernate.cache.use_minimal_puts</literal>
+        forcing a refresh of the second-level cache for all items read from
+        the database</para>
+      </listitem>
+    </itemizedlist>
 
-        </section>
+    <para>To browse the contents of a second-level or query cache region, use
+    the <literal>Statistics</literal> API:</para>
 
-        <section id="performance-cache-transactional">
-            <title>Strategy: transactional</title>
+    <example>
+      <title>Browsing the second-level cache entries via the
+      <classname>Statistics</classname> API</title>
 
-            <para>
-                The <literal>transactional</literal> cache strategy provides support for fully transactional cache
-                providers such as JBoss TreeCache. Such a cache can only be used in a JTA environment and you must 
-                specify <literal>hibernate.transaction.manager_lookup_class</literal>. 
-            </para>
+      <programlisting role="JAVA">Map cacheEntries = sessionFactory.getStatistics()
+        .getSecondLevelCacheStatistics(regionName)
+        .getEntries();</programlisting>
+    </example>
 
-        </section>
+    <para>You will need to enable statistics and, optionally, force Hibernate
+    to keep the cache entries in a more readable format:</para>
 
-        <section id="performance-cache-compat-matrix">
-            <title>Cache-provider/concurrency-strategy compatibility</title>
+    <example>
+      <title>Enabling Hibernate statistics</title>
 
-            <important>
-                <para>
-                    None of the cache providers support all of the cache concurrency strategies.
-                </para>
-            </important>
+      <programlisting>hibernate.generate_statistics true
+hibernate.cache.use_structured_entries true</programlisting>
+    </example>
+  </section>
 
-            <para>
-                The following table shows which providers are compatible with which concurrency strategies.
-            </para>
+  <section id="performance-querycache" revision="1">
+    <title>The Query Cache</title>
 
-            <table frame="topbot">
-                <title>Cache Concurrency Strategy Support</title>
-                <tgroup cols='5' align='left' colsep='1' rowsep='1'>
-                <colspec colname='c1' colwidth="1*"/>
-                <colspec colname='c2' colwidth="1*"/>
-                <colspec colname='c3' colwidth="1*"/>
-                <colspec colname='c4' colwidth="1*"/>
-                <colspec colname='c5' colwidth="1*"/>
-                <thead>
-                <row>
-                  <entry>Cache</entry>
-                  <entry>read-only</entry>
-                  <entry>nonstrict-read-write</entry>
-                  <entry>read-write</entry>
-                  <entry>transactional</entry>
-                </row>
-                </thead>
-                <tbody>
-                <row>
-                    <entry>Hashtable (not intended for production use)</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry> </entry>
-                </row>
-                <row>
-                    <entry>EHCache</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry> </entry>
-                </row>
-                <row>
-                    <entry>OSCache</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry> </entry>
-                </row>
-                <row>
-                    <entry>SwarmCache</entry>
-                    <entry>yes</entry>
-                    <entry>yes</entry>
-                    <entry> </entry>
-                    <entry> </entry>
-                </row>
-                <row>
-                    <entry>JBoss Cache 1.x</entry>
-                    <entry>yes</entry>
-                    <entry> </entry>
-                    <entry> </entry>
-                    <entry>yes</entry>
-                </row>
-                <row>
-                    <entry>JBoss Cache 2</entry>
-                    <entry>yes</entry>
-                    <entry> </entry>
-                    <entry> </entry>
-                    <entry>yes</entry>
-                </row>
-                </tbody>
-                </tgroup>
-            </table>
+    <para>Query result sets can also be cached. This is only useful for
+    queries that are run frequently with the same parameters.</para>
 
-        </section>
+    <section id="performance-querycache-enable">
+      <title>Enabling query caching</title>
 
-    </section>
+      <para>Caching of query results introduces some overhead in terms of your
+      applications normal transactional processing. For example, if you cache
+      results of a query against Person Hibernate will need to keep track of
+      when those results should be invalidated because changes have been
+      committed against Person. That, coupled with the fact that most
+      applications simply gain no benefit from caching query results, leads
+      Hibernate to disable caching of query results by default. To use query
+      caching, you will first need to enable the query cache:</para>
 
-    <section id="performance-sessioncache" revision="2">
-        <title>Managing the caches</title>
+      <programlisting>hibernate.cache.use_query_cache true</programlisting>
 
-        <para>
-            Whenever you pass an object to <literal>save()</literal>, <literal>update()</literal>
-            or <literal>saveOrUpdate()</literal>, and whenever you retrieve an object using 
-            <literal>load()</literal>, <literal>get()</literal>, <literal>list()</literal>, 
-            <literal>iterate()</literal> or <literal>scroll()</literal>, that object is added 
-            to the internal cache of the <literal>Session</literal>. 
-        </para>
-        <para>
-            When <literal>flush()</literal> is subsequently called, the state of that object will 
-            be synchronized with the database. If you do not want this synchronization to occur, or 
-            if you are processing a huge number of objects and need to manage memory efficiently, 
-            the <literal>evict()</literal> method can be used to remove the object and its collections 
-            from the first-level cache.
-        </para>
-        
-        <programlisting role="JAVA"><![CDATA[ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //a huge result set
-while ( cats.next() ) {
-    Cat cat = (Cat) cats.get(0);
-    doSomethingWithACat(cat);
-    sess.evict(cat);
-}]]></programlisting>
-        
-        <para>
-            The <literal>Session</literal> also provides a <literal>contains()</literal> method to determine 
-            if an instance belongs to the session cache.
-        </para>
-        
-        <para>
-            To evict all objects from the session cache, call <literal>Session.clear()</literal>
-        </para>
-        
-        <para>
-            For the second-level cache, there are methods defined on <literal>SessionFactory</literal> for 
-            evicting the cached state of an instance, entire class, collection instance or entire collection 
-            role.
-        </para>
-        
-        <programlisting role="JAVA"><![CDATA[sessionFactory.evict(Cat.class, catId); //evict a particular Cat
-sessionFactory.evict(Cat.class);  //evict all Cats
-sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
-sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections]]></programlisting>
+      <para>This setting creates two new cache regions: <itemizedlist>
+          <listitem>
+            <para><classname>org.hibernate.cache.StandardQueryCache</classname>,
+            holding the cached query results</para>
+          </listitem>
 
-        <para>
-            The <literal>CacheMode</literal> controls how a particular session interacts with the second-level
-            cache:
-        </para>
-        
-        <itemizedlist>
-        <listitem>
-        <para>
-            <literal>CacheMode.NORMAL</literal>: will read items from and write items to the second-level cache
-        </para>
-        </listitem>
-        <listitem>
-        <para>
-            <literal>CacheMode.GET</literal>: will read items from the second-level cache. Do not write to
-            the second-level cache except when updating data
-        </para>
-        </listitem>
-        <listitem>
-        <para>
-            <literal>CacheMode.PUT</literal>: will write items to the second-level cache. Do not read from
-            the second-level cache
-        </para>
-        </listitem>
-        <listitem>
-        <para>
-            <literal>CacheMode.REFRESH</literal>: will write items to the second-level cache. Do not read from
-            the second-level cache.  Bypass the effect of <literal>hibernate.cache.use_minimal_puts</literal> forcing
-            a refresh of the second-level cache for all items read from the database
-        </para>
-        </listitem>
-        </itemizedlist>
-        
-        <para>
-            To browse the contents of a second-level or query cache region, use the <literal>Statistics</literal>
-            API:
-        </para>
-        
-        <programlisting role="JAVA"><![CDATA[Map cacheEntries = sessionFactory.getStatistics()
-        .getSecondLevelCacheStatistics(regionName)
-        .getEntries();]]></programlisting>
-        
-        <para>
-            You will need to enable statistics and, optionally, force Hibernate to keep the cache entries in a
-            more readable format:
-        </para>
-        
-        <programlisting><![CDATA[hibernate.generate_statistics true
-hibernate.cache.use_structured_entries true]]></programlisting>       
-                
+          <listitem>
+            <para><classname>org.hibernate.cache.UpdateTimestampsCache</classname>,
+            holding timestamps of the most recent updates to queryable tables.
+            These are used to validate the results as they are served from the
+            query cache.</para>
+          </listitem>
+        </itemizedlist></para>
+
+      <important>
+        <para>If you configure your underlying cache implementation to use
+        expiry or timeouts is very important that the cache timeout of the
+        underlying cache region for the UpdateTimestampsCache be set to a
+        higher value than the timeouts of any of the query caches. In fact, we
+        recommend that the the UpdateTimestampsCache region not be configured
+        for expiry at all. Note, in particular, that an LRU cache expiry
+        policy is never appropriate.</para>
+      </important>
+
+      <para>As mentioned above, most queries do not benefit from caching or
+      their results. So by default, individual queries are not cached even
+      after enabling query caching. To enable results caching for a particular
+      query, call <literal>org.hibernate.Query.setCacheable(true)</literal>.
+      This call allows the query to look for existing cache results or add its
+      results to the cache when it is executed.</para>
+
+      <note>
+        <para>The query cache does not cache the state of the actual entities
+        in the cache; it caches only identifier values and results of value
+        type. For this reaso, the query cache should always be used in
+        conjunction with the second-level cache for those entities expected to
+        be cached as part of a query result cache (just as with collection
+        caching).</para>
+      </note>
     </section>
 
-    <section id="performance-querycache" revision="1">
-        <title>The Query Cache</title>
+    <section id="performance-querycache-regions">
+      <title>Query cache regions</title>
 
-        <para>
-            Query result sets can also be cached. This is only useful for queries that are run
-            frequently with the same parameters.
-        </para>
+      <para>If you require fine-grained control over query cache expiration
+      policies, you can specify a named cache region for a particular query by
+      calling <literal>Query.setCacheRegion()</literal>.</para>
 
-        <section id="performance-querycache-enable">
-            <title>Enabling query caching</title>
-            <para>
-                Caching of query results introduces some overhead in terms of your applications normal
-                transactional processing.  For example, if you cache results of a query against Person
-                Hibernate will need to keep track of when those results should be invalidated because
-                changes have been committed against Person.  That, coupled with the fact that most
-                applications simply gain no benefit from caching query results, leads Hibernate to
-                disable caching of query results by default.  To use query caching, you will first
-                need to enable the query cache:
-            </para>
-            <programlisting><![CDATA[hibernate.cache.use_query_cache true]]></programlisting>
-            <para>
-                This setting creates two new cache regions:
-                <itemizedlist>
-                    <listitem>
-                        <para>
-                            <classname>org.hibernate.cache.StandardQueryCache</classname>, holding
-                            the cached query results
-                        </para>
-                    </listitem>
-                    <listitem>
-                        <para>
-                            <classname>org.hibernate.cache.UpdateTimestampsCache</classname>, holding
-                            timestamps of the most recent updates to queryable tables.  These are used
-                            to validate the results as they are served from the query cache.
-                        </para>
-                    </listitem>
-                </itemizedlist>
-            </para>
-            <important>
-                <para>
-                    If you configure your underlying cache implementation to use expiry or
-                    timeouts is very important that the cache timeout of the underlying
-                    cache region for the UpdateTimestampsCache be set to a higher value than
-                    the timeouts of any of the query caches.  In fact, we recommend that the
-                    the UpdateTimestampsCache region not be configured for expiry at all.  Note,
-                    in particular, that an LRU cache expiry policy is never appropriate.
-                </para>
-            </important>
-            <para>
-                As mentioned above, most queries do not benefit from caching or their results.  So by
-                default, individual queries are not cached even after enabling query caching. To enable
-                results caching for a particular query, call
-                <literal>org.hibernate.Query.setCacheable(true)</literal>.  This call allows the query
-                to look for existing cache results or add its results to the cache when it is executed.
-            </para>
-            <note>
-                <para>
-                    The query cache does not cache the state of the actual entities in the cache; it
-                    caches only identifier values and results of value type.  For this reaso, the query
-                    cache should always be used in conjunction with the second-level cache for those
-                    entities expected to be cached as part of a query result cache (just as with
-                    collection caching).
-                </para>
-            </note>
-        </section>
-
-        <section id="performance-querycache-regions">
-            <title>Query cache regions</title>
-            <para>
-                If you require fine-grained control over query cache expiration policies, you can
-                specify a named cache region for a particular query by calling
-                <literal>Query.setCacheRegion()</literal>.
-            </para>
-            <programlisting role="JAVA"><![CDATA[List blogs = sess.createQuery("from Blog blog where blog.blogger = :blogger")
+      <programlisting role="JAVA">List blogs = sess.createQuery("from Blog blog where blog.blogger = :blogger")
         .setEntity("blogger", blogger)
         .setMaxResults(15)
         .setCacheable(true)
         .setCacheRegion("frontpages")
-        .list();]]></programlisting>
+        .list();</programlisting>
 
-            <para>
-                If you want to force the query cache to refresh one of its regions (disregard any
-                cached results it finds there) you can use
-                <literal>org.hibernate.Query.setCacheMode(CacheMode.REFRESH)</literal>.  In conjunction
-                with the region you have defined for the given query, Hibernate will selectively force
-                the results cached in that particular region to be refreshed.  This is particularly useful
-                in cases where underlying data may have been updated via a separate process and is a far more
-                efficient alternative to bulk eviction of the region via
-                <literal>org.hibernate.SessionFactory.evictQueries()</literal>.
-            </para>
-        </section>
+      <para>If you want to force the query cache to refresh one of its regions
+      (disregard any cached results it finds there) you can use
+      <literal>org.hibernate.Query.setCacheMode(CacheMode.REFRESH)</literal>.
+      In conjunction with the region you have defined for the given query,
+      Hibernate will selectively force the results cached in that particular
+      region to be refreshed. This is particularly useful in cases where
+      underlying data may have been updated via a separate process and is a
+      far more efficient alternative to bulk eviction of the region via
+      <literal>org.hibernate.SessionFactory.evictQueries()</literal>.</para>
     </section>
+  </section>
 
-    <section id="performance-collections">
-        <title>Understanding Collection performance</title>
+  <section id="performance-collections">
+    <title>Understanding Collection performance</title>
 
-        <para>
-            In the previous sections we have covered collections and their applications.
-            In this section we explore some more issues in relation to
-            collections at runtime.
-        </para>
+    <para>In the previous sections we have covered collections and their
+    applications. In this section we explore some more issues in relation to
+    collections at runtime.</para>
 
-        <section id="performance-collections-taxonomy">
-            <title>Taxonomy</title>
+    <section id="performance-collections-taxonomy">
+      <title>Taxonomy</title>
 
-            <para>Hibernate defines three basic kinds of collections:</para>
+      <para>Hibernate defines three basic kinds of collections:</para>
 
-            <itemizedlist>
-            <listitem>
-                <para>collections of values</para>
-            </listitem>
-            <listitem>
-                <para>one-to-many associations</para>
-            </listitem>
-            <listitem>
-                <para>many-to-many associations</para>
-            </listitem>
-            </itemizedlist>
+      <itemizedlist>
+        <listitem>
+          <para>collections of values</para>
+        </listitem>
 
-            <para>
-                This classification distinguishes the various table and foreign key
-                relationships but does not tell us quite everything we need to know
-                about the relational model. To fully understand the relational structure
-                and performance characteristics, we must also consider the structure of
-                the primary key that is used by Hibernate to update or delete collection
-                rows. This suggests the following classification:
-            </para>
+        <listitem>
+          <para>one-to-many associations</para>
+        </listitem>
 
-            <itemizedlist>
-            <listitem>
-                <para>indexed collections</para>
-            </listitem>
-            <listitem>
-                <para>sets</para>
-            </listitem>
-            <listitem>
-                <para>bags</para>
-            </listitem>
-            </itemizedlist>
+        <listitem>
+          <para>many-to-many associations</para>
+        </listitem>
+      </itemizedlist>
 
-            <para>
-                All indexed collections (maps, lists, and arrays) have a primary key consisting
-                of the <literal>&lt;key&gt;</literal> and <literal>&lt;index&gt;</literal>
-                columns. In this case, collection updates are extremely efficient.
-                The primary key can be efficiently indexed and a particular row can be efficiently
-                located when Hibernate tries to update or delete it.
-            </para>
-                        
-            <para>
-                Sets have a primary key consisting of <literal>&lt;key&gt;</literal> and element
-                columns. This can be less efficient for some types of collection element, particularly
-                composite elements or large text or binary fields, as the database may not be able to index
-                a complex primary key as efficiently.  However, for one-to-many or many-to-many
-                associations, particularly in the case of synthetic identifiers, it is likely to be just
-                as efficient. If you want <literal>SchemaExport</literal> to actually create
-                the primary key of a <literal>&lt;set&gt;</literal>, you must declare all columns
-                as <literal>not-null="true"</literal>.
-            </para>
+      <para>This classification distinguishes the various table and foreign
+      key relationships but does not tell us quite everything we need to know
+      about the relational model. To fully understand the relational structure
+      and performance characteristics, we must also consider the structure of
+      the primary key that is used by Hibernate to update or delete collection
+      rows. This suggests the following classification:</para>
 
-            <para>
-                <literal>&lt;idbag&gt;</literal> mappings define a surrogate key, so they are
-                efficient to update. In fact, they are the best case.
-            </para>
-            
-            <para>
-                Bags are the worst case since they permit duplicate element values and, as they have no
-                index column, no primary key can be defined. Hibernate has no way of distinguishing
-                between duplicate rows. Hibernate resolves this problem by completely removing
-                in a single <literal>DELETE</literal> and recreating the collection whenever it
-                changes. This can be inefficient.
-            </para>
+      <itemizedlist>
+        <listitem>
+          <para>indexed collections</para>
+        </listitem>
 
-            <para>
-                For a one-to-many association, the "primary key" may not be the physical
-                primary key of the database table. Even in this case, the above classification
-                is still useful. It reflects how Hibernate "locates" individual rows of the
-                collection.
-            </para>
+        <listitem>
+          <para>sets</para>
+        </listitem>
 
-        </section>
+        <listitem>
+          <para>bags</para>
+        </listitem>
+      </itemizedlist>
 
-        <section id="performance-collections-mostefficientupdate">
-            <title>Lists, maps, idbags and sets are the most efficient collections to update</title>
+      <para>All indexed collections (maps, lists, and arrays) have a primary
+      key consisting of the <literal>&lt;key&gt;</literal> and
+      <literal>&lt;index&gt;</literal> columns. In this case, collection
+      updates are extremely efficient. The primary key can be efficiently
+      indexed and a particular row can be efficiently located when Hibernate
+      tries to update or delete it.</para>
 
-            <para>
-                From the discussion above, it should be clear that indexed collections
-                and sets allow the most efficient operation in terms of adding,
-                removing and updating elements.
-            </para>
+      <para>Sets have a primary key consisting of
+      <literal>&lt;key&gt;</literal> and element columns. This can be less
+      efficient for some types of collection element, particularly composite
+      elements or large text or binary fields, as the database may not be able
+      to index a complex primary key as efficiently. However, for one-to-many
+      or many-to-many associations, particularly in the case of synthetic
+      identifiers, it is likely to be just as efficient. If you want
+      <literal>SchemaExport</literal> to actually create the primary key of a
+      <literal>&lt;set&gt;</literal>, you must declare all columns as
+      <literal>not-null="true"</literal>.</para>
 
-            <para>
-                There is, arguably, one more advantage that indexed collections have over sets for
-                many-to-many associations or collections of values. Because of the structure of a
-                <literal>Set</literal>, Hibernate does not <literal>UPDATE</literal> a row when
-                an element is "changed". Changes to a <literal>Set</literal> always work via
-                <literal>INSERT</literal> and <literal>DELETE</literal> of individual rows. Once
-                again, this consideration does not apply to one-to-many associations.
-            </para>
+      <para><literal>&lt;idbag&gt;</literal> mappings define a surrogate key,
+      so they are efficient to update. In fact, they are the best case.</para>
 
-            <para>
-                After observing that arrays cannot be lazy, you can conclude that lists, maps and 
-                idbags are the most performant (non-inverse) collection types, with sets not far 
-                behind. You can expect sets to be the most common kind of collection in Hibernate 
-                applications. This is because the "set" semantics are most natural in the relational
-                model.
-            </para>
+      <para>Bags are the worst case since they permit duplicate element values
+      and, as they have no index column, no primary key can be defined.
+      Hibernate has no way of distinguishing between duplicate rows. Hibernate
+      resolves this problem by completely removing in a single
+      <literal>DELETE</literal> and recreating the collection whenever it
+      changes. This can be inefficient.</para>
 
-            <para>
-                However, in well-designed Hibernate domain models, most collections
-                are in fact one-to-many associations with <literal>inverse="true"</literal>. For these
-                associations, the update is handled by the many-to-one end of the association, and so
-                considerations of collection update performance simply do not apply.
-            </para>
+      <para>For a one-to-many association, the "primary key" may not be the
+      physical primary key of the database table. Even in this case, the above
+      classification is still useful. It reflects how Hibernate "locates"
+      individual rows of the collection.</para>
+    </section>
 
-        </section>
+    <section id="performance-collections-mostefficientupdate">
+      <title>Lists, maps, idbags and sets are the most efficient collections
+      to update</title>
 
-        <section id="performance-collections-mostefficentinverse">
-            <title>Bags and lists are the most efficient inverse collections</title>
+      <para>From the discussion above, it should be clear that indexed
+      collections and sets allow the most efficient operation in terms of
+      adding, removing and updating elements.</para>
 
-            <para>
-                There is a particular case, however, in which bags, and also lists,
-                are much more performant than sets. For a collection with <literal>inverse="true"</literal>,
-                the standard bidirectional one-to-many relationship idiom, for example, we can add elements
-                to a bag or list without needing to initialize (fetch) the bag elements. This is because, unlike a <literal>set</literal>,
-                <literal>Collection.add()</literal> or <literal>Collection.addAll()</literal> must always
-                return true for a bag or <literal>List</literal>. This can
-                make the following common code much faster:
-            </para>
+      <para>There is, arguably, one more advantage that indexed collections
+      have over sets for many-to-many associations or collections of values.
+      Because of the structure of a <literal>Set</literal>, Hibernate does not
+      <literal>UPDATE</literal> a row when an element is "changed". Changes to
+      a <literal>Set</literal> always work via <literal>INSERT</literal> and
+      <literal>DELETE</literal> of individual rows. Once again, this
+      consideration does not apply to one-to-many associations.</para>
 
-            <programlisting role="JAVA"><![CDATA[Parent p = (Parent) sess.load(Parent.class, id);
+      <para>After observing that arrays cannot be lazy, you can conclude that
+      lists, maps and idbags are the most performant (non-inverse) collection
+      types, with sets not far behind. You can expect sets to be the most
+      common kind of collection in Hibernate applications. This is because the
+      "set" semantics are most natural in the relational model.</para>
+
+      <para>However, in well-designed Hibernate domain models, most
+      collections are in fact one-to-many associations with
+      <literal>inverse="true"</literal>. For these associations, the update is
+      handled by the many-to-one end of the association, and so considerations
+      of collection update performance simply do not apply.</para>
+    </section>
+
+    <section id="performance-collections-mostefficentinverse">
+      <title>Bags and lists are the most efficient inverse collections</title>
+
+      <para>There is a particular case, however, in which bags, and also
+      lists, are much more performant than sets. For a collection with
+      <literal>inverse="true"</literal>, the standard bidirectional
+      one-to-many relationship idiom, for example, we can add elements to a
+      bag or list without needing to initialize (fetch) the bag elements. This
+      is because, unlike a <literal>set</literal>,
+      <literal>Collection.add()</literal> or
+      <literal>Collection.addAll()</literal> must always return true for a bag
+      or <literal>List</literal>. This can make the following common code much
+      faster:</para>
+
+      <programlisting role="JAVA">Parent p = (Parent) sess.load(Parent.class, id);
 Child c = new Child();
 c.setParent(p);
 p.getChildren().add(c);  //no need to fetch the collection!
-sess.flush();]]></programlisting>
+sess.flush();</programlisting>
+    </section>
 
-        </section>
+    <section id="performance-collections-oneshotdelete">
+      <title>One shot delete</title>
 
-        <section id="performance-collections-oneshotdelete">
-            <title>One shot delete</title>
+      <para>Deleting collection elements one by one can sometimes be extremely
+      inefficient. Hibernate knows not to do that in the case of an
+      newly-empty collection (if you called <literal>list.clear()</literal>,
+      for example). In this case, Hibernate will issue a single
+      <literal>DELETE</literal>.</para>
 
-            <para>
-                Deleting collection elements one by one can sometimes be extremely inefficient. Hibernate
-                knows not to do that in the case of an newly-empty collection
-                (if you called <literal>list.clear()</literal>, for example). In this case, Hibernate will
-                issue a single <literal>DELETE</literal>. 
-            </para>
+      <para>Suppose you added a single element to a collection of size twenty
+      and then remove two elements. Hibernate will issue one
+      <literal>INSERT</literal> statement and two <literal>DELETE</literal>
+      statements, unless the collection is a bag. This is certainly
+      desirable.</para>
 
-            <para>
-                Suppose you added a single element to a collection of size twenty and then remove two elements.
-                Hibernate will issue one <literal>INSERT</literal> statement and two <literal>DELETE</literal>
-                statements, unless the collection is a bag. This is certainly desirable.
-            </para>
+      <para>However, suppose that we remove eighteen elements, leaving two and
+      then add thee new elements. There are two possible ways to
+      proceed</para>
 
-            <para>
-                However, suppose that we remove eighteen elements, leaving two and then add thee new elements.
-                There are two possible ways to proceed
-            </para>
+      <itemizedlist>
+        <listitem>
+          <para>delete eighteen rows one by one and then insert three
+          rows</para>
+        </listitem>
 
-            <itemizedlist>
-            <listitem>
-                <para>delete eighteen rows one by one and then insert three rows</para>
-            </listitem>
-            <listitem>
-                <para>remove the whole collection in one SQL <literal>DELETE</literal> and insert
-                all five current elements one by one</para>
-            </listitem>
-            </itemizedlist>
+        <listitem>
+          <para>remove the whole collection in one SQL
+          <literal>DELETE</literal> and insert all five current elements one
+          by one</para>
+        </listitem>
+      </itemizedlist>
 
-            <para>
-                Hibernate cannot know that the second option is probably quicker.
-                It would probably be undesirable for Hibernate to be that intuitive as such behavior might
-                confuse database triggers, etc.
-            </para>
+      <para>Hibernate cannot know that the second option is probably quicker.
+      It would probably be undesirable for Hibernate to be that intuitive as
+      such behavior might confuse database triggers, etc.</para>
 
-            <para>
-                Fortunately, you can force this behavior (i.e. the second strategy) at any time by discarding
-                (i.e. dereferencing) the original collection and returning a newly instantiated collection with
-                all the current elements. 
-            </para>
-            
-            <para>
-                One-shot-delete does not apply to collections mapped <literal>inverse="true"</literal>.
-            </para>
+      <para>Fortunately, you can force this behavior (i.e. the second
+      strategy) at any time by discarding (i.e. dereferencing) the original
+      collection and returning a newly instantiated collection with all the
+      current elements.</para>
 
-        </section>
-
+      <para>One-shot-delete does not apply to collections mapped
+      <literal>inverse="true"</literal>.</para>
     </section>
+  </section>
 
-    <section id="performance-monitoring" revision="1">
-        <title>Monitoring performance</title>
+  <section id="performance-monitoring" revision="1">
+    <title>Monitoring performance</title>
 
-        <para>
-            Optimization is not much use without monitoring and access to performance numbers.
-            Hibernate provides a full range of figures about its internal operations.
-            Statistics in Hibernate are available per <literal>SessionFactory</literal>.
-        </para>
+    <para>Optimization is not much use without monitoring and access to
+    performance numbers. Hibernate provides a full range of figures about its
+    internal operations. Statistics in Hibernate are available per
+    <literal>SessionFactory</literal>.</para>
 
-        <section id="performance-monitoring-sf" revision="2">
-            <title>Monitoring a SessionFactory</title>
+    <section id="performance-monitoring-sf" revision="2">
+      <title>Monitoring a SessionFactory</title>
 
-            <para>
-                You can access <literal>SessionFactory</literal> metrics in two ways.
-                Your first option is to call <literal>sessionFactory.getStatistics()</literal> and
-                read or display the <literal>Statistics</literal> yourself.
-            </para>
+      <para>You can access <literal>SessionFactory</literal> metrics in two
+      ways. Your first option is to call
+      <literal>sessionFactory.getStatistics()</literal> and read or display
+      the <literal>Statistics</literal> yourself.</para>
 
-            <para>
-                Hibernate can also use JMX to publish metrics if you enable the
-                <literal>StatisticsService</literal> MBean. You can enable a single MBean for all your
-                <literal>SessionFactory</literal> or one per factory. See the following code for
-                minimalistic configuration examples:
-            </para>
+      <para>Hibernate can also use JMX to publish metrics if you enable the
+      <literal>StatisticsService</literal> MBean. You can enable a single
+      MBean for all your <literal>SessionFactory</literal> or one per factory.
+      See the following code for minimalistic configuration examples:</para>
 
-            <programlisting role="JAVA"><![CDATA[// MBean service registration for a specific SessionFactory
+      <programlisting role="JAVA">// MBean service registration for a specific SessionFactory
 Hashtable tb = new Hashtable();
 tb.put("type", "statistics");
 tb.put("sessionFactory", "myFinancialApp");
@@ -1436,93 +1537,86 @@
 
 StatisticsService stats = new StatisticsService(); // MBean implementation
 stats.setSessionFactory(sessionFactory); // Bind the stats to a SessionFactory
-server.registerMBean(stats, on); // Register the Mbean on the server]]></programlisting>
+server.registerMBean(stats, on); // Register the Mbean on the server</programlisting>
 
-
-<programlisting role="JAVA"><![CDATA[// MBean service registration for all SessionFactory's
+      <programlisting role="JAVA">// MBean service registration for all SessionFactory's
 Hashtable tb = new Hashtable();
 tb.put("type", "statistics");
 tb.put("sessionFactory", "all");
 ObjectName on = new ObjectName("hibernate", tb); // MBean object name
 
 StatisticsService stats = new StatisticsService(); // MBean implementation
-server.registerMBean(stats, on); // Register the MBean on the server]]></programlisting>
+server.registerMBean(stats, on); // Register the MBean on the server</programlisting>
 
-            <para>
-                You can activate and deactivate the monitoring for a <literal>SessionFactory</literal>:
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        at configuration time, set <literal>hibernate.generate_statistics</literal> to <literal>false</literal>
-                    </para>
-                </listitem>
-            </itemizedlist>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        at runtime: <literal>sf.getStatistics().setStatisticsEnabled(true)</literal>
-                        or <literal>hibernateStatsBean.setStatisticsEnabled(true)</literal>
-                    </para>
-                </listitem>
-            </itemizedlist>
+      <para>You can activate and deactivate the monitoring for a
+      <literal>SessionFactory</literal>:</para>
 
-            <para>
-                Statistics can be reset programmatically using the <literal>clear()</literal> method.
-                A summary can be sent to a logger (info level) using the <literal>logSummary()</literal>
-                method.
-            </para>
+      <itemizedlist>
+        <listitem>
+          <para>at configuration time, set
+          <literal>hibernate.generate_statistics</literal> to
+          <literal>false</literal></para>
+        </listitem>
+      </itemizedlist>
 
-        </section>
+      <itemizedlist>
+        <listitem>
+          <para>at runtime:
+          <literal>sf.getStatistics().setStatisticsEnabled(true)</literal> or
+          <literal>hibernateStatsBean.setStatisticsEnabled(true)</literal></para>
+        </listitem>
+      </itemizedlist>
 
-        <section id="performance-monitoring-metrics" revision="1">
-            <title>Metrics</title>
+      <para>Statistics can be reset programmatically using the
+      <literal>clear()</literal> method. A summary can be sent to a logger
+      (info level) using the <literal>logSummary()</literal> method.</para>
+    </section>
 
-            <para>
-                Hibernate provides a number of metrics, from basic information to more specialized information
-                that is only relevant in certain scenarios. All available counters are described in the
-                <literal>Statistics</literal> interface API, in three categories:
-            </para>
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        Metrics related to the general <literal>Session</literal> usage, such as
-                        number of open sessions, retrieved JDBC connections, etc.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Metrics related to the entities, collections, queries, and caches as a
-                        whole (aka global metrics).
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Detailed metrics related to a particular entity, collection, query or
-                        cache region.
-                    </para>
-                </listitem>
-            </itemizedlist>
+    <section id="performance-monitoring-metrics" revision="1">
+      <title>Metrics</title>
 
-            <para>
-                For example, you can check the cache hit, miss, and put ratio of entities, collections
-                and queries, and the average time a query needs. Be aware that the number of milliseconds
-                is subject to approximation in Java. Hibernate is tied to the JVM precision and on some
-                platforms this might only be accurate to 10 seconds.
-            </para>
+      <para>Hibernate provides a number of metrics, from basic information to
+      more specialized information that is only relevant in certain scenarios.
+      All available counters are described in the
+      <literal>Statistics</literal> interface API, in three categories:</para>
 
-            <para>
-                Simple getters are used to access the global metrics (i.e. not tied to a particular entity,
-                collection, cache region, etc.). You can access the metrics of a particular entity, collection
-                or cache region through its name, and through its HQL or SQL representation for queries. Please
-                refer to the <literal>Statistics</literal>, <literal>EntityStatistics</literal>,
-                <literal>CollectionStatistics</literal>, <literal>SecondLevelCacheStatistics</literal>,
-                and <literal>QueryStatistics</literal> API Javadoc for more information. The following
-                code is a simple example:
-            </para>
+      <itemizedlist>
+        <listitem>
+          <para>Metrics related to the general <literal>Session</literal>
+          usage, such as number of open sessions, retrieved JDBC connections,
+          etc.</para>
+        </listitem>
 
-            <programlisting role="JAVA"><![CDATA[Statistics stats = HibernateUtil.sessionFactory.getStatistics();
+        <listitem>
+          <para>Metrics related to the entities, collections, queries, and
+          caches as a whole (aka global metrics).</para>
+        </listitem>
 
+        <listitem>
+          <para>Detailed metrics related to a particular entity, collection,
+          query or cache region.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>For example, you can check the cache hit, miss, and put ratio of
+      entities, collections and queries, and the average time a query needs.
+      Be aware that the number of milliseconds is subject to approximation in
+      Java. Hibernate is tied to the JVM precision and on some platforms this
+      might only be accurate to 10 seconds.</para>
+
+      <para>Simple getters are used to access the global metrics (i.e. not
+      tied to a particular entity, collection, cache region, etc.). You can
+      access the metrics of a particular entity, collection or cache region
+      through its name, and through its HQL or SQL representation for queries.
+      Please refer to the <literal>Statistics</literal>,
+      <literal>EntityStatistics</literal>,
+      <literal>CollectionStatistics</literal>,
+      <literal>SecondLevelCacheStatistics</literal>, and
+      <literal>QueryStatistics</literal> API Javadoc for more information. The
+      following code is a simple example:</para>
+
+      <programlisting role="JAVA">Statistics stats = HibernateUtil.sessionFactory.getStatistics();
+
 double queryCacheHitCount  = stats.getQueryCacheHitCount();
 double queryCacheMissCount = stats.getQueryCacheMissCount();
 double queryCacheHitRatio =
@@ -1536,18 +1630,14 @@
         entityStats.getInsertCount()
         + entityStats.getUpdateCount()
         + entityStats.getDeleteCount();
-log.info(Cat.class.getName() + " changed " + changes + "times"  );]]></programlisting>
+log.info(Cat.class.getName() + " changed " + changes + "times"  );</programlisting>
 
-            <para>
-                You can work on all entities, collections, queries and region caches, by retrieving
-                the list of names of entities, collections, queries and region caches using the
-                following methods: <literal>getQueries()</literal>, <literal>getEntityNames()</literal>,
-                <literal>getCollectionRoleNames()</literal>, and
-                <literal>getSecondLevelCacheRegionNames()</literal>.
-            </para>
-
-        </section>
-
+      <para>You can work on all entities, collections, queries and region
+      caches, by retrieving the list of names of entities, collections,
+      queries and region caches using the following methods:
+      <literal>getQueries()</literal>, <literal>getEntityNames()</literal>,
+      <literal>getCollectionRoleNames()</literal>, and
+      <literal>getSecondLevelCacheRegionNames()</literal>.</para>
     </section>
-
+  </section>
 </chapter>



More information about the hibernate-commits mailing list