Author: gbadner
Date: 2010-03-24 14:19:00 -0400 (Wed, 24 Mar 2010)
New Revision: 19108
Added:
core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml
Log:
HHH-4940 : Document immutable/read-only entity and immutable collection functionality
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml
===================================================================
---
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml 2010-03-24
17:14:35 UTC (rev 19107)
+++
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml 2010-03-24
18:19:00 UTC (rev 19108)
@@ -80,6 +80,7 @@
<xi:include href="content/inheritance_mapping.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/session_api.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/readonly.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/transactions.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/events.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/batch.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
Added: core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml
(rev 0)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml 2010-03-24
18:19:00 UTC (rev 19108)
@@ -0,0 +1,859 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 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" [
+<!ENTITY % BOOK_ENTITIES SYSTEM
"../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
+%BOOK_ENTITIES;
+
+]>
+
+<chapter id="readonly">
+ <title>Read-only entities</title>
+
+ <important>
+ <para>
+ Hibernate's treatment of <emphasis>read-only</emphasis>
entities may
+ differ from what you may have encountered elsewhere. Incorrect usage
+ may cause unexpected results.
+ </para>
+ </important>
+
+ <para>
+ When an entity is read-only:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hibernate does not dirty-check the entity's simple
+ properties or single-ended associations;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate will not update simple properties or updatable
+ single-ended associations;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate will not update the version of the read-only
+ entity if only simple properties or single-ended
+ updatable associations are changed;
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In some ways, Hibernate treats read-only entities the same as entities that are
+ not read-only:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hibernate cascades operations to associations as
+ defined in the entity mapping.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate updates the version if the entity has a
+ collection with changes that dirties the entity;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A read-only entity can be deleted.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Even if an entity is not read-only, its collection association can
+ be affected if it contains a read-only entity.
+ </para>
+
+ <para>
+ For details about the affect of read-only entities on different
+ property and association types, see
+ <xref linkend="readonly-proptypes"/>.
+ </para>
+
+ <para>
+ For details about how to make entities read-only, see
+ <xref linkend="readonly-api"/>
+ </para>
+
+ <para>
+ Hibernate does some optimizing for read-only entities:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ It saves execution time by not dirty-checking simple properties or
+ single-ended associations.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ It saves memory by deleting database snapshots.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="readonly-api">
+ <title>Making persistent entities read-only</title>
+
+ <para>
+ Only persistent entities can be made read-only. Transient and
+ detached entities must be put in persistent state before they
+ can be made read-only.
+ </para>
+
+ <para>
+ Hibernate provides the following ways to make persistent entities read-only:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ you can map an entity class as
<emphasis>immutable</emphasis>;
+ when an entity of an immutable class is made persistent,
+ Hibernate automatically makes it read-only.
+ see <xref linkend="readonly-api-immutable"/> for
details
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can change a default so that entities loaded
+ into the session by Hibernate are automatically
+ made read-only; see <xref
linkend="readonly-api-loaddefault"/> for details
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can make an HQL query or criteria read-only so
+ that entities loaded when the query or criteria executes,
+ scrolls, or iterates, are automatically
+ made read-only; see <xref
linkend="readonly-api-querycriteria"/> for details
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can make a persistent entity that is already in the
+ in the session read-only; see
+ <xref linkend="readonly-api-entity"/> for details
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="readonly-api-immutable">
+ <title>Entities of immutable classes</title>
+
+ <para>
+ When an entity instance of an immutable class is made
+ persistent, Hibernate automatically makes it read-only.
+ </para>
+ <para>
+ An entity of an immutable class can created
+ and deleted the same as an entity of a mutable class.
+ </para>
+
+ <para>
+ Hibernate treats a persistent entity of an immutable
+ class the same way as a read-only persistent entity
+ of a mutable class. The only exception is that
+ Hibernate will not allow an entity of an immutable
+ class to be changed so it is not read-only.
+ </para>
+
+ </section>
+
+ <section id="readonly-api-loaddefault">
+ <title>Loading persistent entities as read-only</title>
+
+ <note>
+ <para>
+ Entities of immutable classes are automatically loaded
+ as read-only.
+ </para>
+ </note>
+
+ <para>
+ To change the default behavior so Hibernate loads entity
+ instances of mutable classes into the session and automatically
+ makes them read-only, call:
+ </para>
+ <programlisting role="Java">Session.setDefaultReadOnly( true
);</programlisting>
+
+ <para>
+ To change the default back so entities loaded by Hibernate are not
+ made read-only, call:
+ </para>
+ <programlisting role="Java">Session.setDefaultReadOnly(
false );</programlisting>
+
+ <para>
+ You can determine the current setting by calling:
+ </para>
+ <programlisting
role="Java">Session.isDefaultReadOnly();</programlisting>
+
+ <para>
+ If Session.isDefaultReadOnly() returns true, entities loaded by
+ the following are automatically made read-only:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Session.load()
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Session.get()
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Session.merge()
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ executing, scrolling, or iterating HQL queries and
+ criteria; to override this setting for a particular
+ HQL query or criteria see
+ <xref linkend="readonly-api-querycriteria"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Changing this default has no effect on:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ persistent entities already in the session when the
+ default was changed
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ persistent entities that are refreshed via
+ Session.refresh(); a refreshed persistent
+ entity will only be read-only if it was
+ read-only before refreshing
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ persistent entities added by the application via
+ Session.persist(), Session.save(), and Session.update()
+ Session.saveOrUpdate()
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+ <section id="readonly-api-querycriteria">
+ <title>Loading read-only entities from an HQL
query/criteria</title>
+
+ <note>
+ <para>
+ Entities of immutable classes are automatically loaded
+ as read-only.
+ </para>
+ </note>
+
+ <para>
+ If Session.isDefaultReadOnly() returns false (the default)
+ when an HQL query or criteria executes, then entities
+ and proxies of mutable classes loaded by the query will
+ not be read-only.
+ </para>
+
+ <para>
+ You can override this behavior so that entities and proxies loaded
+ by an HQL query or criteria are automatically made read-only.
+ </para>
+
+ <para>
+ For an HQL query, call:
+ </para>
+ <programlisting role="Java">Query.setReadOnly( true
);</programlisting>
+
+ <para>
+ <literal>Query.setReadOnly( true )</literal> must be called
before
+ <literal>Query.list()</literal>,
<literal>Query.uniqueResult()</literal>,
+ <literal>Query.scroll()</literal>, or
<literal>Query.iterate()</literal>
+ </para>
+
+ <para>
+ For an HQL criteria, call:
+ </para>
+ <programlisting role="Java">Criteria.setReadOnly( true
);</programlisting>
+
+ <para>
+ <literal>Criteria.setReadOnly( true )</literal> must be
called before
+ <literal>Criteria.list()</literal>,
<literal>Criteria.uniqueResult()</literal>,
+ or <literal>Criteria.scroll()</literal>
+ </para>
+
+ <para>
+ Entities and proxies that exist in the session before being returned
+ by an HQL query or criteria are not affected.
+ </para>
+
+ <para>
+ Uninitialized persistent collections returned by the query are
+ not affected. Later, when the collection is initialized,
+ entities loaded into the session will be read-only if
+ Session.isDefaultReadOnly() returns true.
+ </para>
+
+ <para>
+ Using <literal>Query.setReadOnly( true )</literal> or
+ <literal>Criteria.setReadOnly( true )</literal> works well
+ when a single HQL query or criteria loads all the entities and
+ intializes all the proxies and collections that the application
+ needs to be read-only.
+ </para>
+
+ <para>
+ When it is not possible to load and initialize all
+ necessary entities in a single query or criteria,
+ you can temporarily change the session default to load
+ entities as read-only before the query is executed.
+ Then you can explicitly initialize proxies and collections
+ before restoring the session default.
+ </para>
+
+ <programlisting role="Java">
+Session session = factory.openSession();
+Transaction tx = session.beginTransaction();
+
+setDefaultReadOnly( true );
+Contract contract =
+ ( Contract ) session.createQuery(
+ "from Contract where customerName = 'Sherman'" )
+ .uniqueResult();
+Hibernate.initialize( contract.getPlan() );
+Hibernate.initialize( contract.getVariations() );
+Hibernate.initialize( contract.getNotes() );
+setDefaultReadOnly( false );
+...
+tx.commit();
+session.close();
+
+</programlisting>
+
+ <para>
+ If Session.isDefaultReadOnly() returns true, then you can
+ use Query.setReadOnly( false ) and Criteria.setReadOnly( false )
+ to override this session setting and load entities that are
+ not read-only.
+ </para>
+
+ </section>
+
+ <section id="readonly-api-entity">
+ <title>Making a persistent entity read-only</title>
+ <note>
+ <para>
+ Persistent entities of immutable classes are automatically
+ made read-only.
+ </para>
+ </note>
+
+ <para>
+ To make a persistent entity or proxy read-only, call:
+ </para>
+ <programlisting>Session.setReadOnly(entityOrProxy,
true)</programlisting>
+
+ <para>
+ To change a read-only entity or proxy of a mutable class so
+ it is no longer read-only, call:
+ </para>
+ <programlisting>Session.setReadOnly(entityOrProxy,
false)</programlisting>
+
+ <important>
+ <para>
+ When a read-only entity or proxy is changed so it is no longer
+ read-only, Hibernate assumes that the current state of the
+ read-only entity is consistent with its database representation.
+ If this is not true, then any non-flushed changes made before
+ or while the entity was read-only, will be ignored.
+ </para>
+ </important>
+
+ <para>
+ To throw away non-flushed changes and make the persistent entity
+ consistent with its database representation, call:
+ </para>
+ <programlisting role="Java">session.refresh( entity
);</programlisting>
+
+ <para>
+ To flush changes made before or while the entity
+ was read-only and make the database representation
+ consistent with the current state of the persistent
+ entity:
+ </para>
+<programlisting role="Java">
+// evict the read-only entity so it is detached
+session.evict( entity );
+
+// make the detached entity (with the non-flushed changes) persistent
+session.update( entity );
+
+// now entity is no longer read-only and its changes can be flushed
+s.flush();
+</programlisting>
+ </section>
+ </section>
+
+ <section id="readonly-proptypes">
+ <title>Read-only affect on property type</title>
+
+ <para>
+ The following table summarizes how different property types are
+ affected by making an entity read-only.
+ </para>
+
+ <table frame="topbot" id="readonly-proptype-summary">
+ <title>Affect of read-only entity on property types</title>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Property/Association Type</entry>
+ <entry>Changes flushed to DB?</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Simple
+ <para>
+ (<xref
linkend="readonly-proptypes-simple"/>)
+ </para>
+ </entry>
+ <entry>no*</entry>
+ </row>
+ <row>
+ <entry>
+ <para>Unidirectional one-to-one</para>
+ <para>Unidirectional many-to-one</para>
+ <para>
+ (<xref
linkend="readonly-proptypes-singleended-unidir"/>)
+ </para>
+ </entry>
+
+ <entry>
+ <para>no*</para>
+ <para>no*</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Unidirectional one-to-many</para>
+ <para>Unidirectional many-to-many</para>
+ <para>
+ (<xref
linkend="readonly-proptypes-manyended-unidir"/>)
+ </para>
+ </entry>
+ <entry>
+ <para>yes</para>
+ <para>yes</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Bidirectional one-to-one</para>
+ <para>
+ (<xref
linkend="readonly-proptypes-onetoone-bidir"/>)
+ </para>
+ </entry>
+ <entry>only if the owning entity is not
read-only*</entry>
+ </row>
+ <row>
+ <entry>
+ <para>Bidirectional
one-to-many/many-to-one</para>
+ <para>inverse collection</para>
+ <para>non-inverse collection</para>
+ <para>
+ (<xref
linkend="readonly-proptypes-onetomany-manytoone"/>)
+ </para>
+ </entry>
+ <entry>
+ <para> </para>
+ <para>only added/removed entities that are not
read-only*</para>
+ <para>yes</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Bidirectional many-to-many</para>
+ <para>
+ (<xref
linkend="readonly-proptypes-manytomany-bidir"/>)
+ </para>
+ </entry>
+ <entry>yes</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ * Behavior is different when the entity having the property/association
+ is read-only, compared to when it is not read-only.
+ </para>
+
+ <section id="readonly-proptypes-simple">
+ <title>Simple properties</title>
+
+ <para>
+ When a persistent object is read-only, Hibernate does not
+ dirty-check simple properties.
+ </para>
+
+ <para>
+ Hibernate will not synchronize simple property state changes
+ to the database. If you have automatic versioning, Hibernate
+ will not increment the version if any simple properties change.
+ </para>
+
+ <programlisting role="Java">
+Session session = factory.openSession();
+Transaction tx = session.beginTransaction();
+
+// get a contract and make it read-only
+Contract contract = ( Contract ) session.get( Contract.class, contractId );
+session.setReadOnly( contract, true );
+
+// contract.getCustomerName() is "Sherman"
+contract.setCustomerName( "Yogi" );
+tx.commit();
+
+tx = session.beginTransaction();
+
+contract = ( Contract ) session.get( Contract.class, contractId );
+// contract.getCustomerName() is still "Sherman"
+...
+tx.commit();
+session.close();
+ </programlisting>
+
+ </section>
+
+ <section id="readonly-prop-types-unidir">
+ <title>Unidirectional associations</title>
+
+ <section id="readonly-proptypes-singleended-unidir">
+ <title>Unidirectional one-to-one and many-to-one</title>
+
+ <para>
+ Hibernate treats unidirectional one-to-one and many-to-one
+ associations in the same way when the owning entity is
+ read-only.
+ </para>
+
+ <para>
+ We use the term <emphasis>unidirectional single-ended
+ association</emphasis> when referring to functionality
+ that is common to unidirectional one-to-one and many-to-one
+ associations.
+ </para>
+
+ <para>
+ Hibernate does not dirty-check unidirectional single-ended
+ associations when the owning entity is read-only.
+ </para>
+
+ <para>
+ If you change a read-only entity's reference to a
+ unidirectional single-ended association to null,
+ or to refer to a different entity, that change
+ will not be flushed to the database.
+ </para>
+
+ <note>
+ <para>
+ If an entity is of an immutable class,
+ then its references to unidirectional single-ended
+ associations must be assigned when that
+ entity is first created. Because the entity is
+ automatically made read-only, these references can
+ not be updated.
+ </para>
+ </note>
+
+ <para>
+ If automatic versioning is used, Hibernate will not
+ increment the version due to local changes to
+ unidirectional single-ended associations.
+ </para>
+
+ <para>
+ In the following examples, Contract has a unidirectional
+ many-to-one association with Plan. Contract cascades save and
+ update operations to the association.
+ </para>
+
+ <para>
+ The following shows that changing a read-only entity's
+ many-to-one association reference to null has no effect
+ on the entity's database representation.
+ </para>
+
+<programlisting role="Java">// get a contract with an existing plan;
+// make the contract read-only and set its plan to null
+tx = session.beginTransaction();
+Contract contract = ( Contract ) session.get( Contract.class, contractId );
+session.setReadOnly( contract, true );
+contract.setPlan( null );
+tx.commit();
+
+// get the same contract
+tx = session.beginTransaction();
+contract = ( Contract ) session.get( Contract.class, contractId );
+
+// contract.getPlan() still refers to the original plan;
+
+tx.commit();
+session.close();</programlisting>
+
+ <para>
+ The following shows that, even though
+ an update to a read-only entity's many-to-one
+ association has no affect on the entity's
+ database representation, flush still cascades
+ the save-update operation to the locally
+ changed association.
+ </para>
+
+<programlisting role="Java">// get a contract with an existing plan;
+// make the contract read-only and change to a new plan
+tx = session.beginTransaction();
+Contract contract = ( Contract ) session.get( Contract.class, contractId );
+session.setReadOnly( contract, true );
+Plan newPlan = new Plan( "new plan"
+contract.setPlan( newPlan);
+tx.commit();
+
+// get the same contract
+tx = session.beginTransaction();
+contract = ( Contract ) session.get( Contract.class, contractId );
+newPlan = ( Contract ) session.get( Plan.class, newPlan.getId() );
+
+// contract.getPlan() still refers to the original plan;
+// newPlan is non-null because it was persisted when
+// the previous transaction was committed;
+
+tx.commit();
+session.close();</programlisting>
+
+ </section>
+
+ <section id="readonly-proptypes-manyended-unidir">
+ <title>Unidirectional one-to-many and many-to-many</title>
+
+ <para>
+ Hibernate treats unidirectional one-to-many
+ and many-to-many associations owned by a read-only
+ entity the same as when owned by an entity that is not
+ read-only.
+ </para>
+
+ <para>
+ Hibernate dirty-checks unidirectional one-to-many and
+ many-to-many associations;
+ </para>
+
+ <para>
+ The collection can contain entities that
+ are read-only, as well as entities
+ that are not read-only.
+ </para>
+
+ <para>
+ Entities can be added and removed from the
+ collection; changes are flushed to the database.
+ </para>
+
+ <para>
+ If automatic versioning is used, Hibernate will
+ update the version due to changes in the collection
+ if they dirty the owning entity.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="readonly-proptypes-bidir">
+ <title>Bidirectional associations</title>
+
+ <section id="readonly-proptypes-onetoone-bidir">
+ <title>Bidirectional one-to-one</title>
+
+ <para>
+ If a read-only entity owns a bidirectional
+ one-to-one association:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hibernate does not dirty-check the association.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ updates that change the association reference
+ to null or to refer to a different entity
+ will not be flushed to the database.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If automatic versioning is used, Hibernate will not
+ increment the version due to local changes to
+ the association.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <para>
+ If an entity is of an immutable class,
+ and it owns a bidirectional one-to-one
+ association, then its reference must be
+ assigned when that entity is first created.
+ Because the entity is automatically made
+ read-only, these references cannot be updated.
+ </para>
+ </note>
+
+ <para>
+ When the owner is not read-only, Hibernate treats
+ an association with a read-only entity the same
+ as when the association is with an entity that is
+ not read-only.
+ </para>
+
+ </section>
+
+ <section id="readonly-proptypes-onetomany-manytoone">
+ <title>Bidirectional one-to-many/many-to-one</title>
+
+ <para>
+ A read-only entity has no impact on a bidirectional
+ one-to-many/many-to-one association if:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the read-only entity is on the one-to-many side
+ using an inverse collection;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the read-only entity is on the one-to-many side
+ using a non-inverse collection;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the one-to-many side uses a non-inverse collection
+ that contains the read-only entity
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ When the one-to-many side uses an inverse collection:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a read-only entity can only be added to the collection
+ when it is created;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a read-only entity can only be removed from the
+ collection by an orphan delete or by explicitly
+ deleting the entity.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+ <section id="readonly-proptypes-manytomany-bidir">
+ <title>Bidirectional many-to-many</title>
+ <para>
+ Hibernate treats bidirectional many-to-many
+ associations owned by a read-only entity the
+ same as when owned by an entity that is not
+ read-only.
+ </para>
+
+ <para>
+ Hibernate dirty-checks bidirectional many-to-many
+ associations.
+ </para>
+
+ <para>
+ The collection on either side of the association
+ can contain entities that are read-only, as well
+ as entities that are not read-only.
+ </para>
+
+ <para>
+ Entities are added and removed from both sides
+ of the collection; changes are flushed to the
+ database.
+ </para>
+
+ <para>
+ If automatic versioning is used, Hibernate will
+ update the version due to changes in both sides of
+ the collection if they dirty the entity owning the
+ respective collections.
+ </para>
+
+ </section>
+
+ </section>
+ </section>
+</chapter>