HHH-154 and versions

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@5964 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Christian Bauer 2005-02-28 12:43:52 +00:00
parent 4b1c7c0cc7
commit 4b13e3544f
15 changed files with 70 additions and 67 deletions

View File

@ -33,7 +33,7 @@
<bookinfo>
<title>HIBERNATE - Relational Persistence for Idiomatic Java</title>
<subtitle>Hibernate Reference Documentation</subtitle>
<releaseinfo>3.0 beta4</releaseinfo>
<releaseinfo>3.0</releaseinfo>
</bookinfo>
<toc/>

View File

@ -436,7 +436,7 @@
by a query that names any superclass or implemented interface or the class and that instances
of any subclass of the class will be returned by a query that names the class itself.
<emphasis>Explicit</emphasis> polymorphism means that class instances will be returned only
be queries that explicitly name that class and that queries that name the class will return
by queries that explicitly name that class and that queries that name the class will return
only instances of subclasses mapped inside this <literal>&lt;class&gt;</literal> declaration
as a <literal>&lt;subclass&gt;</literal> or <literal>&lt;joined-subclass&gt;</literal>. For
most purposes the default, <literal>polymorphism="implicit"</literal>, is appropriate.
@ -898,7 +898,7 @@
You must instantiate an instance of the persistent class itself and populate its
identifier properties before you can <literal>load()</literal> the persistent state
associated with a composite key. We will describe a much more
convenient approach where the composite identifier is implemented as a seperate class
convenient approach where the composite identifier is implemented as a separate class
in <xref linkend="components-compositeid"/>. The attributes described below apply only
to this alternative approach:
</para>
@ -1404,7 +1404,7 @@
</callout>
<callout arearefs="manytoone5">
<para>
<literal>join</literal> (optional - defaults to <literal>select</literal>):
<literal>fetch</literal> (optional - defaults to <literal>select</literal>):
Chooses between outer-join fetching or sequential select fetching.
</para>
</callout>
@ -1641,7 +1641,7 @@
</class>]]></programlisting>
<para>
A newly saved instance of <literal>Person</literal> is then assigned the same primar
A newly saved instance of <literal>Person</literal> is then assigned the same primary
key value as the <literal>Employee</literal> instance refered with the <literal>employee</literal>
property of that <literal>Person</literal>.
</para>
@ -1767,7 +1767,7 @@
<para>
The <literal>&lt;dynamic-component&gt;</literal> element allows a <literal>Map</literal>
to be mapped as a component, where the property names refer to keys of the map, see
<xref linken="components-dynamic"/>.
<xref linkend="components-dynamic"/>.
</para>
</sect2>
@ -2533,7 +2533,7 @@
<para>
An entity's persistent state consists of references to other entities and
instances of <emphasis>value</emphasis> types. Values are primitives,
collections (not whats inside a collection), components and certain immutable
collections (not what's inside a collection), components and certain immutable
objects. Unlike entities, values (in particular collections and components)
<emphasis>are</emphasis> persisted and deleted by reachability. Since value
objects (and primitives) are persisted and deleted along with their containing
@ -2560,10 +2560,10 @@
</para>
<para>
The challenge is to map the Java type system (and the developers definition of
The challenge is to map the Java type system (and the developers' definition of
entities and value types) to the SQL/database type system. The bridge between
both systems is provided by Hibernate: for entities we use
<literal>&lt;class&gt;</literal>, <literal>&lt;subclass&lt;</literal> and so on.
<literal>&lt;class&gt;</literal>, <literal>&lt;subclass&gt;</literal> and so on.
For value types we use <literal>&lt;property&gt;</literal>,
<literal>&lt;component&gt;</literal>, etc, usually with a <literal>type</literal>
attribute. The value of this attribute is the name of a Hibernate
@ -2750,7 +2750,7 @@
<para>
The <literal>CompositeUserType</literal>, <literal>EnhancedUserType</literal>,
and <literal>UserCollectionType</literal> and <literal>UserVersionType</literal>
<literal>UserCollectionType</literal>, and <literal>UserVersionType</literal>
interfaces provide support for more specialized uses.
</para>
@ -2795,11 +2795,11 @@
Even though Hibernate's rich range of built-in types and support for components means you
will very rarely <emphasis>need</emphasis> to use a custom type, it is nevertheless
considered good form to use custom types for (non-entity) classes that occur frequently
in your application. For example, a <literal>MonetoryAmount</literal> class is a good
in your application. For example, a <literal>MonetaryAmount</literal> class is a good
candidate for a <literal>CompositeUserType</literal>, even though it could easily be mapped
as a component. One motivation for this is abstraction. With a custom type, your mapping
documents would be future-proofed against possible changes in your way of representing
monetory values.
monetary values.
</para>
</sect2>

View File

@ -239,10 +239,10 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<literal>not-null="true"</literal>.
</para>
<programlisting><![CDATA[<key column="productSerialNumber" not-null="cascade"/>]]></programlisting>
<programlisting><![CDATA[<key column="productSerialNumber" not-null="true"/>]]></programlisting>
<para>
The foreign key constraint may use <literal>ON CASCADE DELETE</literal>.
The foreign key constraint may use <literal>ON DELETE CASCADE</literal>.
</para>
<programlisting><![CDATA[<key column="productSerialNumber" on-delete="cascade"/>]]></programlisting>
@ -261,7 +261,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
Collections may contain almost any other Hibernate type, including all basic types,
custom types, components, and of course, references to other entities. This is an
important distinction: an object in a collection might be handled with "value"
semantics (it's lifecycle fully depends on the collection owner) or it might be a
semantics (its lifecycle fully depends on the collection owner) or it might be a
reference to another entity, with its own lifecycle. In the latter case, only the
"link" between the two objects is considered to be state held by the collection.
</para>
@ -492,7 +492,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<para>
<literal>fetch</literal> (optional - defaults to <literal>join</literal>):
enables outer-join or sequential select fetching for this association. This
is a special case, for full eager fetching (in a single <literal>SELECT</literal>)
is a special case; for full eager fetching (in a single <literal>SELECT</literal>)
of an entity and its many-to-many relationships to other entities, you would
enable <literal>join</literal> fetching not only of the collection itself,
but also with this attribute on the <literal>&lt;many-to-many&gt;</literal>

View File

@ -92,7 +92,7 @@
</orderedlist>
<para>
<literal>hibernate.properties</literal> is the easiest approach is you
<literal>hibernate.properties</literal> is the easiest approach if you
want to get started quickly.
</para>

View File

@ -153,7 +153,7 @@ public class AuditInterceptor implements Interceptor, Serializable {
A custom listener should implement the appropriate interface for the event it wants to
process and/or extend one of the convenience base classes (or even the default event
listeners used by Hibernate out-of-the-box as these are declared non-final for this
purpose). Custom listeners can either be registered programatically through the
purpose). Custom listeners can either be registered programmatically through the
<literal>Configuration</literal> object, or specified in the Hibernate configuration
XML (declarative configuration through the properties file is not supported). Here's an
example of a custom load event listener:
@ -183,7 +183,7 @@ public class AuditInterceptor implements Interceptor, Serializable {
</hibernate-configuration>]]></programlisting>
<para>
Instead, you may register it programatically:
Instead, you may register it programmatically:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration();
@ -192,8 +192,8 @@ cfg.getSessionEventListenerConfig().setLoadEventListener( new MyLoadListener() )
<para>
Listeners registered declaratively cannot share instances. If the same class name is
used in multiple <literal>&lt;listener/&gt;</literal> elements, each reference will
result in a seperate instance of that class. If you need the capability to share
listener instances between listener types you must use the programatic registration
result in a separate instance of that class. If you need the capability to share
listener instances between listener types you must use the programmatic registration
approach.
</para>

View File

@ -12,7 +12,7 @@
The following model of the relationship between <literal>Employer</literal> and
<literal>Employee</literal> uses an actual entity class (<literal>Employment</literal>)
to represent the association. This is done because there might be more than one
period of employment for the same two parties. Components are used to model monetory
period of employment for the same two parties. Components are used to model monetary
values and employee names.
</para>
@ -50,7 +50,7 @@
<property name="startDate" column="start_date"/>
<property name="endDate" column="end_date"/>
<component name="hourlyRate" class="MonetoryAmount">
<component name="hourlyRate" class="MonetaryAmount">
<property name="amount">
<column name="hourly_rate" sql-type="NUMERIC(12, 2)"/>
</property>

View File

@ -271,7 +271,7 @@ session.update(parent);
session.flush();]]></programlisting>
<para>
Well, thats all very well for the case of a generated identifier, but what about assigned identifiers
Well, that's all very well for the case of a generated identifier, but what about assigned identifiers
and composite identifiers? This is more difficult, since Hibernate can't use the identifier property to
distinguish between a newly instantiated object (with an identifier assigned by the user) and an
object loaded in a previous session. In this case, Hibernate will either use the timestamp or version

View File

@ -91,7 +91,7 @@
</sect2>
<sect2>
<title>Table per class subclass</title>
<title>Table per subclass</title>
<para>
A table per subclass mapping would look like:

View File

@ -8,7 +8,7 @@
A <emphasis>fetching strategy</emphasis> is the strategy Hibernate will
use for retrieving associated objects if the application needs to
navigate the association. Fetch strategies may be declared in the O/R
mapping metadata, or over-ridden by particular HQL or
mapping metadata, or over-ridden by a particular HQL or
<literal>Criteria</literal> query.
</para>
@ -130,7 +130,7 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
<para>
<emphasis>The fetch strategy specified in the mapping document does not affect
HQL queries</emphasis>
HQL queries.</emphasis>
</para>
<para>
@ -162,7 +162,7 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
role per persistent class or query to be fetched per outer join. Hibernate forbids
Cartesian products when possible, <literal>SELECT</literal>ing two collections per
outer join would create one. This would almost always be slower than two (lazy or
non-defered) <literal>SELECT</literal>s. The restriction to a single outer-joined
non-deferred) <literal>SELECT</literal>s. The restriction to a single outer-joined
collection applies to both the mapping fetching strategies and to HQL/Criteria
queries.
</para>
@ -250,7 +250,7 @@ System.out.println( dc.getWeight() ); // 11.0]]></programlisting>
</para>
<para>
These problems are all due to fundamental limitations in Java's single inheritence model.
These problems are all due to fundamental limitations in Java's single inheritance model.
If you wish 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. eg.
</para>
@ -263,8 +263,8 @@ System.out.println( dc.getWeight() ); // 11.0]]></programlisting>
</class>]]></programlisting>
<para>
where <literal>Cat</literal> implements the interface <literal>ICat</literal> and
<literal>DomesticCat</literal> implements the interface <literal>IDomesticCat</literal>. Then
where <literal>CatImpl</literal> implements the interface <literal>Cat</literal> and
<literal>DomesticCatImpl</literal> implements the interface <literal>DomesticCat</literal>. Then
proxies for instances of <literal>Cat</literal> and <literal>DomesticCat</literal> may be returned
by <literal>load()</literal> or <literal>iterate()</literal>. (Note that <literal>list()</literal>
does not usually return proxies.)
@ -314,7 +314,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<title>Initializing collections and proxies</title>
<para>
A <literal>LazyInitializationException</literal> will be thrown by Hibernate if an unitialized
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>, ie. when
the entity owning the collection or having the reference to the proxy is in the detached state.
</para>
@ -328,7 +328,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
The static methods <literal>Hibernate.initialize()</literal> and <literal>Hibernate.isInitialized()</literal>
provide the application with a convenient way of working with lazyily initialized collections or
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
@ -380,7 +380,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
You may also attach a previously loaded object to a new <literal>Session</literal>
with <literal>merge()</literal> or <literal>lock()</literal> before
accessing unitialized collections (or other proxies). No, Hibernate does not,
accessing uninitialized collections (or other proxies). No, Hibernate does not,
and certainly <emphasis>should</emphasis> not do this automatically, since it
would introduce ad hoc transaction semantics!
</para>
@ -513,7 +513,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
A different (better?) way to avoid unnecessary column reads, at least for
read-only transactons is to use the projection features of HQL. This avoids
read-only transactions is to use the projection features of HQL. This avoids
the need for buildtime bytecode processing.
</para>
@ -650,7 +650,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
If your application needs to read but never modify instances of a persistent class, a
<literal>read-only</literal> cache may be used. This is the simplest and best performing
strategy. Its even perfectly safe for use in a cluster.
strategy. It's even perfectly safe for use in a cluster.
</para>
<programlisting><![CDATA[<class name="eg.Immutable" mutable="false">
@ -914,7 +914,7 @@ hibernate.cache.use_structured_entries true]]></programlisting>
<para>
If the query should force a refresh of its query cache region, you should call
<literal>Query.setCacheMode(CacheMode.REFRESH)</literal>. This is particularly useful
in cases where underlying data may have been updated via a seperate process (i.e.,
in cases where underlying data may have been updated via a separate process (i.e.,
not modified through Hibernate) and allows the application to selectively refresh
particular query result sets. This is a more efficient alternative to eviction of
a query cache region via <literal>SessionFactory.evictQueries()</literal>.
@ -1176,7 +1176,7 @@ server.registerMBean(stats, on); //we register the MBean]]></programlisting>
</listitem>
</itemizedlist>
<para>Statistics can be reset programatically using the <literal>clear()</literal> method. A summary
can be sent logger (info level) using the <literal>logSummary()</literal> method.</para>
can be sent to a logger (info level) using the <literal>logSummary()</literal> method.</para>
</sect2>
<sect2 id="performance-monitoring-metrics" revision="1">
<title>Metrics</title>
@ -1216,10 +1216,12 @@ server.registerMBean(stats, on); //we register the MBean]]></programlisting>
<literal>SecondLevelCacheStatistics</literal> and <literal>QueryStatistics</literal> API for more informations.
</para>
<programlisting><![CDATA[Statistics stats = sf.getStatistics();
double hitRatio = (double) stats.getQueryCacheHitCount() / ( stats.getQueryCacheHitCount() + stats.getQueryCacheMissCount() );
double hitRatio = (double) stats.getQueryCacheHitCount()
/ ( stats.getQueryCacheHitCount() + stats.getQueryCacheMissCount() );
log.info("Query Hit ratio:" + hitRatio);
EntityStatistics entityStats = stats.getEntityStatistics( Cat.class.getName() );
int changes = entityStats.getInsertCount() + entityStats.getUpdateCount() + entityStats.getDeleteCount();
int changes = entityStats.getInsertCount()
+ entityStats.getUpdateCount() + entityStats.getDeleteCount();
log.info(Cat.class.getName() + " changes:" + changes);]]></programlisting>
<para>
In order to work on all detailed entities, collections, queries and region caches statistics, you can retrieve
@ -1232,9 +1234,9 @@ log.info(Cat.class.getName() + " changes:" + changes);]]></programlisting>
<title>Understanding metrics</title>
<para>
You can find interesting informations while looking at metrics. An entity/collection/query with a high cache
miss ratio (cache miss superior to cache hit) should not be cached: the benefit of caching is not significant
miss ratio (cache miss greater than cache hit) should not be cached: the benefit of caching is not significant
for your application and use case.
An entity/collection/query with a cache put way superior to its cache hit should not be cached either: you spend
An entity/collection/query with a cache put much greater than its cache hit should not be cached either: you spend
a lot of resources in caching without efficiently use it.
A session factory having more open sessions than closed ones shows a session leak which must be addressed.
A use case using lots of connections might show a good candidate for a conversion to the session per user

View File

@ -302,7 +302,8 @@ public class DomesticCat extends Cat {
<para>
Note that a business key does not have to be as solid as a database
primary key candidate. Immutable or unique properties are usually good
primary key candidate (see <xref linkend="transactions-basics-identity"/>).
Immutable or unique properties are usually good
candidates for a business key.
</para>

View File

@ -688,7 +688,7 @@ having cat.color in (eg.Color.TABBY, eg.Color.BLACK)]]></programlisting>
<para>
SQL functions and aggregate functions are allowed in the <literal>having</literal>
and <literal>order by</literal> clauses, if supported by the underlying database (ie.
and <literal>order by</literal> clauses, if supported by the underlying database (eg.
not in MySQL).
</para>

View File

@ -71,7 +71,7 @@
<para>
The <literal>{cat.*}</literal> notation used above is a shorthand for "all properties".
Alternatively, you may list the columns explicity, but even then you must let Hibernate
inject the SQL column aliases for each property. The placeholders for a column alias is
inject the SQL column aliases for each property. The placeholder for a column alias is
just the property name qualified by the table alias. In the following example, we retrieve
<literal>Cat</literal>s from a different table (<literal>cat_log</literal>) to the one
declared in the mapping metadata. Notice that we may even use the property aliases in the
@ -159,12 +159,12 @@ List loggedCats = sess.createSQLQuery(sql)
</class>]]></programlisting>
<para>
The SQL is directly execute in your database, so you are free to use any dialect
The SQL is directly executed in your database, so you are free to use any dialect
you like.
</para>
<para>
Stored procedures are support if the <literal>callable</literal> attribute is set:
Stored procedures are supported if the <literal>callable</literal> attribute is set:
</para>
<programlisting><![CDATA[<class name="Person">

View File

@ -31,7 +31,7 @@
been instantiated using the <literal>new</literal> operator, and it
is not associated with a Hibernate <literal>Session</literal>. It has no
persistent representation in the database and no identifier value has been
assigned. Transient instances will be destroyed by the garbage collector of
assigned. Transient instances will be destroyed by the garbage collector if
the application doesn't hold a reference anymore. Use the Hibernate
<literal>Session</literal> to make an object persistent (and let Hibernate
take care of the SQL statements that need to be executed for this transition).
@ -64,7 +64,7 @@
</itemizedlist>
<para>
We'll know discuss the states and state transitions (and the Hibernate methods that
We'll now discuss the states and state transitions (and the Hibernate methods that
trigger a transition) in more detail.
</para>
@ -111,7 +111,7 @@ sess.save( pk, new Long(1234) );]]></programlisting>
<para>
If the object you make persistent has associated objects (e.g. the
<literal>kittens</literal> collection role) in the previous example),
<literal>kittens</literal> collection in the previous example),
these objects may be made persistent in any order you like unless you
have a <literal>NOT NULL</literal> constraint upon a foreign key column.
There is never a risk of violating foreign key constraints. However, you
@ -256,7 +256,7 @@ Cat mother = (Cat) session.createQuery(
<para>
A query is usually executed by invoking <literal>list()</literal>, the
result of the query will be loaded completely into a collection in memory.
Entity instance retrieved by a query are in persistent state. The
Entity instances retrieved by a query are in persistent state. The
<literal>uniqueResult()</literal> method offers a shortcut if you
know your query will only return a single object.
</para>
@ -498,7 +498,7 @@ List cats = q.list();]]></programlisting>
);]]></programlisting>
<para>
The returned collection is considered a bag, and its a copy of the given
The returned collection is considered a bag, and it's a copy of the given
collection. The original collection is not modified (this is contrary to
the implication of the name "filter", but consistent with expected behavior).
</para>
@ -900,7 +900,7 @@ session2.close();]]></programlisting>
<listitem>
<para>
<literal>ReplicationMode.EXCEPTION</literal> - throw an exception if there is
and existing database row with the same identifier
an existing database row with the same identifier
</para>
</listitem>
<listitem>
@ -933,7 +933,7 @@ session2.close();]]></programlisting>
<itemizedlist spacing="compact">
<listitem>
<para>
before from some query executions
before some query executions
</para>
</listitem>
<listitem>

View File

@ -38,7 +38,7 @@
</itemizedlist>
<para>
There's actually another utitily living in Hibernate Extensions: <literal>ddl2hbm</literal>.
There's actually another utility living in Hibernate Extensions: <literal>ddl2hbm</literal>.
It is considered deprecated and will no longer be maintained, Middlegen does a better job
for the same task.
</para>
@ -456,7 +456,7 @@ new SchemaUpdate(cfg).execute(false);]]></programlisting>
<para>
The Hibernate code generator may be used to generate skeletal Java implementation classes
from a Hibernate mapping file. This tool is included in the Hibernate Extensions package
(a seperate download).
(a separate download).
</para>
<para>
@ -515,7 +515,7 @@ new SchemaUpdate(cfg).execute(false);]]></programlisting>
<para>
This config file declares a global meta attribute "implements" and specify two renderers, the
default one (BasicRenderer) and a renderer that generates Finder's (See more in "Basic Finder
default one (BasicRenderer) and a renderer that generates Finders (See more in "Basic Finder
generation" below).
</para>
@ -771,7 +771,7 @@ public class Person implements Serializable, IAuditable {
<para>
Note: This applies to <emphasis>all</emphasis> <literal>&lt;meta&gt;</literal>-tags.
Thus it can also e.g. be used to specify that all fields should be declare protected,
Thus it can also e.g. be used to specify that all fields should be declared protected,
instead of the default private. This is done by adding <literal>&lt;meta
attribute="scope-field"&gt;protected&lt;/meta&gt;</literal> at e.g. just under the
<literal>&lt;class&gt;</literal> tag and all fields of that class will be protected.

View File

@ -226,7 +226,7 @@
JVM identity for database identity is guaranteed by Hibernate. However, while the application
might concurrently access the "same" (persistent identity) business object in two different
sessions, the two instances will actually be "different" (JVM identity). Conflicts are
resolved using (automatic versioning) at flush/commit time, using an optmistic approach.
resolved using (automatic versioning) at flush/commit time, using an optimistic approach.
</para>
<para>
@ -272,7 +272,7 @@
<listitem>
<para>
A <literal>Session</literal> is not thread-safe. Things which are supposed to work
concurrently, like HTTP requests, session beans, or swing workers, will cause race
concurrently, like HTTP requests, session beans, or Swing workers, will cause race
conditions if a <literal>Session</literal> instance would be shared. If you keep your
Hibernate <literal>Session</literal> in your <literal>HttpSession</literal> (discussed
later), you should consider synchronizing access to your Http session. Otherwise,
@ -332,7 +332,7 @@
</para>
<para>
However, it is often desireable to keep your persistence layer portable. Hibernate offers a wrapper
However, it is often desirable to keep your persistence layer portable. Hibernate offers a wrapper
API called <literal>Transaction</literal> that translates into the native transaction system of
your deployment environment. This API is optional (using database transactions is not!) and you don't
have to use it if database portability provided by Hibernate is all you need.
@ -399,7 +399,7 @@ finally {
<para>
Note that you will very likely never see this piece of code in a normal application;
fatal (system) exceptions should always be catched at the "top". In other words, the
fatal (system) exceptions should always be caught at the "top". In other words, the
code that executes Hibernate calls (in the persistence layer) and the code that handles
<literal>RuntimeException</literal> (and usually can only clean up and exit) are in
different layers. This can be a challenge to design yourself and you should use J2EE/EJB
@ -490,7 +490,7 @@ finally {
transaction, call <literal>Session.close()</literal> and discard the
<literal>Session</literal> instance. Certain methods of <literal>Session</literal>
will <emphasis>not</emphasis> leave the session in a consistent state. No
exception thrown by Hibernate can be treaded as recoverable. Ensure that the
exception thrown by Hibernate can be treated as recoverable. Ensure that the
<literal>Session</literal> will be closed by calling <literal>close()</literal>
in a <literal>finally</literal> block.
</para>
@ -618,7 +618,7 @@ session.disconnect(); // Return JDBC connection ]]></programlisting>
This pattern is problematic if the <literal>Session</literal> is too big to
be stored during user think time, e.g. an <literal>HttpSession</literal> should
be kept as small as possible. As the <literal>Session</literal> is also the
(mandatory) first-level cache and contains all loaded objects, we can propably
(mandatory) first-level cache and contains all loaded objects, we can probably
use this strategy only for a few request/response cycles. This is indeed
recommended, as the <literal>Session</literal> will soon also have stale data.
</para>
@ -669,7 +669,7 @@ session.close();]]></programlisting>
<para>
You may disable Hibernate's automatic version increment for particular properties and
collections by setting the <literal>optmistic-lock</literal> mapping attribute to
collections by setting the <literal>optimistic-lock</literal> mapping attribute to
<literal>false</literal>. Hibernate will then no longer increment versions if the
property is dirty.
</para>
@ -679,8 +679,8 @@ session.close();]]></programlisting>
might also access the same database and don't know how to handle version numbers or
even timestamps. In both cases, versioning can't rely on a particular column in a table.
To force a version check without a version or timestamp property mapping, with a
comparison of the state of all fields in a row, turn on <literal>optmistic-lock="all"</literal>
in the <literal>&lt;class&gt;</literal> mapping. Note that this concpetually only works
comparison of the state of all fields in a row, turn on <literal>optimistic-lock="all"</literal>
in the <literal>&lt;class&gt;</literal> mapping. Note that this concepetually only works
if Hibernate can compare the old and new state, i.e. if you use a single long
<literal>Session</literal> and not session-per-request-with-detached-objects.
</para>