HHH-4940 : Document immutable/read-only entity and immutable collection functionality
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19108 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
98628c4a0e
commit
039bb48ccf
|
@ -80,6 +80,7 @@
|
||||||
<xi:include href="content/inheritance_mapping.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
<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/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/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/events.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
<xi:include href="content/batch.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
<xi:include href="content/batch.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
|
|
@ -0,0 +1,858 @@
|
||||||
|
<?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>
|
Loading…
Reference in New Issue