<?xml version='1.0' encoding='utf-8' ?>

<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" >
  <title>Locking</title>
  <para>
    Locking refers to actions taken to prevent data in a relational database from changing between the time it is read
    and the time that it is used.
  </para>
  <para>
    Your locking strategy can be either <firstterm>optimistic</firstterm> or <firstterm>pessimistic</firstterm>.
  </para>
  <variablelist>
    <title>Locking strategies</title>
    <varlistentry>
      <term>Optimistic</term>
      <listitem>
        <para>
          Optimistic locking assumes that multiple transactions can complete without affecting each other, and that
          therefore transactions can proceed without locking the data resources that they affect. Before committing,
          each transaction verifies that no other transaction has modified its data. If the check reveals conflicting
          modifications, the committing transaction rolls back<footnote><para><link xl:href="http://en.wikipedia.org/wiki/Optimistic_locking" /></para></footnote>.
        </para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>Pessimistic</term>
      <listitem>
        <para>
          Pessimistic locking assumes that concurrent transactions will conflict with each other, and requires resources
          to be locked after they are read and only unlocked after the application has finished using the data.
        </para>
      </listitem>
    </varlistentry>
  </variablelist>
  <para>
    Hibernate provides mechanisms for implementing both types of locking in your applications.
  </para>
  <section>
    <title>Optimistic</title>
    <para>
      When your application uses long transactions or conversations that span several database transactions, you can
      store versioning data, so that if the same entity is updated by two conversations, the last to commit changes is
      informed of the conflict, and does not override the other conversation's work. This approach guarantees some
      isolation, but scales well and works particularly well in <firstterm>Read-Often Write-Sometimes</firstterm>
      situations.
    </para>
    <para>
      Hibernate provides two different mechanisms for storing versioning information, a dedicated version number or a
      timestamp.
    </para>
    <variablelist>
      <varlistentry>
        <term>Version number</term>
        <listitem>
          <para>

          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Timestamp</term>
        <listitem>
          <para>

          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <note>
      <para>
        A version or timestamp property can never be null for a detached instance. Hibernate detects any instance with a
        null version or timestamp as transient, regardless of other unsaved-value strategies that you specify. Declaring
        a nullable version or timestamp property is an easy way to avoid problems with transitive reattachment in
        Hibernate, especially useful if you use assigned identifiers or composite keys.
      </para>
    </note>
    
    <section>
      <title>Dedicated version number</title>
      <para>
        The version number mechanism for optimistic locking is provided through a <literal>@Version</literal>
        annotation.
      </para>
      <example>
        <title>The @Version annotation</title>
        <programlisting language="Java" role="JAVA"><xi:include href="extras/version_annotation.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
        <para>
          Here, the version property is mapped to the <literal>OPTLOCK</literal> column, and the entity manager uses it
          to detect conflicting updates, and prevent the loss of updates that would be overwritten by a
          <firstterm>last-commit-wins</firstterm> strategy.
        </para>
      </example>
      <para>
        The version column can be any kind of type, as long as you define and implement the appropriate
        <classname>UserVersionType</classname>.
      </para>
      <para>
        Your application is forbidden from altering the version number set by Hibernate. To artificially increase the
        version number, see the documentation for properties
        <property>LockModeType.OPTIMISTIC_FORCE_INCREMENT</property> or
        <property>LockModeType.PESSIMISTIC_FORCE_INCREMENTcheck</property> in the Hibernate Entity Manager reference
        documentation.
      </para>
      <note>
        <title>Database-generated version numbers</title>
        <para>
          If the version number is generated by the database, such as a trigger, use the annotation
          <literal>@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)</literal>.
        </para>
      </note>
      <example>
        <title>Declaring a version property in <filename>hbm.xml</filename></title>
        <programlisting language="XML" role="XML"><xi:include href="extras/version_property.xml"
        xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
        <informaltable>
          <tgroup cols="2">
            <tbody>
              <row>
                <entry>column</entry>
                <entry><para>The name of the column holding the version number. Optional, defaults to the property
                name. </para></entry>
              </row>
              <row>
                <entry>name</entry>
                <entry><para>The name of a property of the persistent class.</para></entry>
              </row>
              <row>
                <entry>type</entry>
                <entry><para>The type of the version number. Optional, defaults to
                <literal>integer</literal>.</para></entry>
              </row>
              <row>
                <entry>access</entry>
                <entry><para>Hibernate's strategy for accessing the property value. Optional, defaults to
                <literal>property</literal>.</para></entry>
              </row>
              <row>
                <entry>unsaved-value</entry>
                <entry><para>Indicates that an instance is newly instantiated and thus unsaved. This distinguishes it
                from detached instances that were saved or loaded in a previous session. The default value,
                <literal>undefined</literal>, indicates that the identifier property value should be
                used. Optional.</para></entry>
              </row>
              <row>
                <entry>generated</entry>
                <entry><para>Indicates that the version property value is generated by the database. Optional, defaults
                to <literal>never</literal>.</para></entry>
              </row>
              <row>
                <entry>insert</entry>
                <entry><para>Whether or not to include the <code>version</code> column in SQL <code>insert</code>
                statements. Defaults to <literal>true</literal>, but you can set it to <literal>false</literal> if the
                database column is defined with a default value of <literal>0</literal>.</para></entry>
              </row>
            </tbody>
          </tgroup>
        </informaltable>
      </example>
    </section>
    
    <section>
      <title>Timestamp</title>
      <para>
        Timestamps are a less reliable way of optimistic locking than version numbers, but can be used by applications
        for other purposes as well. Timestamping is automatically used if you the <code>@Version</code> annotation on a
        <type>Date</type> or <type>Calendar</type>.
      </para>
      <example>
        <title>Using timestamps for optimistic locking</title>
        <programlisting language="Java" role="JAVA"><xi:include href="extras/timestamp_version.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
      </example>
      <para>
        Hibernate can retrieve the timestamp value from the database or the JVM, by reading the value you specify for
        the <code>@org.hibernate.annotations.Source</code> annotation. The value can be either
        <literal>org.hibernate.annotations.SourceType.DB</literal> or
        <literal>org.hibernate.annotations.SourceType.VM</literal>. The default behavior is to use the database, and is
        also used if you don't specify the annotation at all.
      </para>
      <para>
        The timestamp can also be generated by the database instead of Hibernate, if you use the
        <code>@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)</code> annotation.
      </para>
      <example>
        <title>The timestamp element in <filename>hbm.xml</filename></title>
        <programlisting language="XML" role="XML"><xi:include href="extras/timestamp_version.xml"
        xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
        <informaltable>
          <tgroup cols="2">
            <tbody>
              <row>
                <entry>column</entry>
                <entry><para>The name of the column which holds the timestamp. Optional, defaults to the property
                namel</para></entry>
              </row>
              <row>
                <entry>name</entry>
                <entry><para>The name of a JavaBeans style property of Java type Date or Timestamp of the persistent
                class.</para></entry>
              </row>
              <row>
                <entry>access</entry>
                <entry><para>The strategy Hibernate uses to access the property value. Optional, defaults to
                <literal>property</literal>.</para></entry>
              </row>
              <row>
                <entry>unsaved-value</entry> <entry><para>A version property which indicates than instance is newly
                instantiated, and unsaved. This distinguishes it from detached instances that were saved or loaded in a
                previous session. The default value of <literal>undefined</literal> indicates that Hibernate uses the
                identifier property value.</para></entry>
              </row>
              <row>
                <entry>source</entry>
                <entry><para>Whether Hibernate retrieves the timestamp from the database or the current
                JVM. Database-based timestamps incur an overhead because Hibernate needs to query the database each time
                to determine the incremental next value. However, database-derived timestamps are safer to use in a
                clustered environment. Not all database dialects are known to support the retrieval of the database's
                current timestamp. Others may also be unsafe for locking, because of lack of precision.</para></entry>
              </row>
              <row>
                <entry>generated</entry>
                <entry><para>Whether the timestamp property value is generated by the database. Optional, defaults to
                <literal>never</literal>.</para></entry>
              </row>
            </tbody>
          </tgroup>
        </informaltable>
      </example>
    </section>

  </section>
  
  <section>
    <title>Pessimistic</title>
    <para>
      Typically, you only need to specify an isolation level for the JDBC connections and let the database handle
      locking issues. If you do need to obtain exclusive pessimistic locks or re-obtain locks at the start of a new
      transaction, Hibernate gives you the tools you need.
    </para>
    <note>
      <para>
        Hibernate always uses the locking mechanism of the database, and never lock objects in memory.
      </para>
    </note>
    <section>
      <title>The <classname>LockMode</classname> class</title>
      <para>
        The <classname>LockMode</classname> class defines the different lock levels that Hibernate can acquire.
      </para>
      <informaltable>
        <tgroup cols="2">
          <tbody>
            <row>
              <entry>LockMode.WRITE</entry>
              <entry><para>acquired automatically when Hibernate updates or inserts a row.</para></entry>
            </row>
            <row>
              <entry>LockMode.UPGRADE</entry>
              <entry><para>acquired upon explicit user request using <code>SELECT ... FOR UPDATE</code> on databases
              which support that syntax.</para></entry>
            </row>
            <row>
              <entry>LockMode.UPGRADE_NOWAIT</entry>
              <entry><para>acquired upon explicit user request using a <code>SELECT ... FOR UPDATE NOWAIT</code> in
              Oracle.</para></entry>
            </row>
            <row>
              <entry>LockMode.UPGRADE_SKIPLOCKED</entry>
              <entry><para>acquired upon explicit user request using a <code>SELECT ... FOR UPDATE SKIP LOCKED</code> in
              Oracle, or <code>SELECT ... with (rowlock,updlock,readpast) in SQL Server</code>.</para></entry>
            </row>
            <row>
              <entry>LockMode.READ</entry>
              <entry><para>acquired automatically when Hibernate reads data under <phrase>Repeatable Read</phrase> or
              <phrase>Serializable</phrase> isolation level. It can be re-acquired by explicit user
              request.</para></entry>
            </row>
            <row>
              <entry>LockMode.NONE</entry>
              <entry><para>The absence of a lock. All objects switch to this lock mode at the end of a
              Transaction. Objects associated with the session via a call to <methodname>update()</methodname> or
              <methodname>saveOrUpdate()</methodname> also start out in this lock mode. </para></entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
      <para>
        The explicit user request mentioned above occurs as a consequence of any of the following actions:
      </para>
      <itemizedlist>
        <listitem>
          <para>
            A call to <methodname>Session.load()</methodname>, specifying a LockMode.
          </para>
        </listitem>
        <listitem>
          <para>
            A call to <methodname>Session.lock()</methodname>.
          </para>
        </listitem>
        <listitem>
          <para>
            A call to <methodname>Query.setLockMode()</methodname>.
          </para>
        </listitem>
      </itemizedlist>
      <para>
        If you call <methodname>Session.load()</methodname> with option <option>UPGRADE</option>,
        <option>UPGRADE_NOWAIT</option> or <option>UPGRADE_SKIPLOCKED</option>, and the requested object is not already
        loaded by the session, the object is loaded using <code>SELECT ... FOR UPDATE</code>. If you call 
        <methodname>load()</methodname> for an object that is already loaded with a less restrictive lock than the one 
        you request, Hibernate calls <methodname>lock()</methodname> for that object.
      </para>
      <para>
        <methodname>Session.lock()</methodname> performs a version number check if the specified lock mode is
        <literal>READ</literal>, <literal>UPGRADE</literal>, <literal>UPGRADE_NOWAIT</literal> or 
        <literal>UPGRADE_SKIPLOCKED</literal>. In the case of <literal>UPGRADE</literal>, 
        <literal>UPGRADE_NOWAIT</literal> or <literal>UPGRADE_SKIPLOCKED</literal>, <code>SELECT ... FOR UPDATE</code> 
	syntax is used.
      </para>
      <para>
        If the requested lock mode is not supported by the database, Hibernate uses an appropriate alternate mode
        instead of throwing an exception. This ensures that applications are portable.
      </para>
    </section>
  </section>
</chapter>
