alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (Transactions.xml)

This example Hibernate source code file (Transactions.xml) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

hibernate, hibernate, if, in, it, java, jdbc, jta, jta, session, session, the, the, this

The Hibernate Transactions.xml source code

<?xml version='1.0' encoding='utf-8' ?>
<!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_Development_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter>
    <title>Transactions and concurrency control

    <section>
        <title>Defining Transaction
        <para>
            It is important to understand that the term transaction has many related, yet different meanings in relation
            to persistence and Object/Relational Mapping.  In most use cases these definitions align, but that is not
            always the case.
        </para>
        <itemizedlist>
            <listitem>
                <para>
                    It might refer to the physical transaction with the database.
                </para>
            </listitem>
            <listitem>
                <para>
                    It might refer to the logical notion of a transaction as related to a persistence context.
                </para>
            </listitem>
            <listitem>
                <para>
                    It might refer to the application notion of a Unit-of-Work, as defined by the archetypal pattern.
                </para>
            </listitem>
            <note>
                <para>
                    This documentation largely treats the physical and logic notions of transaction as one-in-the-same.
                </para>
            </note>
        </itemizedlist>

    </section>

    <section>
        <title>Physical Transactions
        <para>
            Hibernate uses the JDBC API for persistence.  In the world of Java there are 2 well defined mechanism
            for dealing with transactions in JDBC: JDBC, itself, and JTA.  Hibernate supports both mechanisms for
            integrating with transactions and allowing applications to manage physical transactions.
        </para>
        <para>
            The first concept in understanding Hibernate transaction support is the
            <interfacename>org.hibernate.engine.transaction.spi.TransactionFactory interface which
            serves 2 main functions:
        </para>
        <itemizedlist>
            <listitem>
                <para>
                    It allows Hibernate to understand the transaction semantics of the environment.  Are we operating
                    in a JTA environment?  Is a physical transaction already currently active?  etc.
                </para>
            </listitem>
            <listitem>
                <para>
                    It acts as a factory for <interfacename>org.hibernate.Transaction instances which
                    are used to allow applications to manage and check the state of transactions.
                    <interfacename>org.hibernate.Transaction is Hibernate's notion of a logical
                    transaction.  JPA has a similar notion in the
                    <interfacename>javax.persistence.EntityTransaction interface.
                </para>
            </listitem>
        </itemizedlist>
        <para>
            <interfacename>org.hibernate.engine.transaction.spi.TransactionFactory is a
            standard Hibernate service.  The default initiator,
            <classname>org.hibernate.engine.transaction.internal.TransactionFactoryInitiator,
            looks for a <literal>hibernate.transaction.factory_class configuration setting to determine
            the factory to use.
            <!-- todo : see service registry appendix -->
        </para>

        <section>
            <title>Physical Transactions - JDBC
            <para>
                JDBC-based transaction management leverages the JDBC defined methods
                <methodname>java.sql.Connection.commit() and
                <methodname>java.sql.Connection.rollback() (JDBC does not define and explicit
                method of beginning a transaction).  In Hibernate, this approach is represented by the
                <classname>org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory class.
            </para>
        </section>

        <section>
            <title>Physical Transactions - JTA
            <para>
                JTA-based transaction management leverages the
                <interfacename>javax.transaction.TransactionManager interface as obtained from
                <interfacename>org.hibernate.service.jta.platform.spi.JtaPlatform API.  This approach
                is represented by the
                <classname>org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory class.
                <!-- todo : see service registry appendix -->
            </para>
        </section>


        <section>
            <title>Physical Transactions - CMT
            <para>
                CMT-based transaction management leverages the
                <interfacename>javax.transaction.UserTransaction interface as obtained from
                <interfacename>org.hibernate.service.jta.platform.spi.JtaPlatform API.  This approach
                is represented by the
                <classname>org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory class.
                <!-- todo : see service registry appendix -->
            </para>
        </section>

        <section>
            <title>Physical Transactions - Custom
            <para>
                Its is also possible to plug in ones own transaction approach by implementing the
                <interfacename>org.hibernate.engine.transaction.spi.TransactionFactory contract.
                The default service initiator has built-in support for understanding custom transaction approaches
                via the <literal>hibernate.transaction.factory_class which can name either:
            </para>
            <itemizedlist>
                <listitem>
                    <para>
                        The instance of <interfacename>org.hibernate.engine.transaction.spi.TransactionFactory
                        to use.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        The name of a class implementing
                        <interfacename>org.hibernate.engine.transaction.spi.TransactionFactory
                        to use.  The expectation is that the implementation class have a no-argument constructor.
                    </para>
                </listitem>
            </itemizedlist>
        </section>

        <section>
            <title>Physical Transactions - Legacy
            <para>
                During development of 4.0, most of these classes named here were moved to new packages.  To help
                facilitate upgrading, Hibernate will also recognize the legacy names here for a short period of time.
            </para>
            <itemizedlist>
                <listitem>
                    <para>
                        <literal>org.hibernate.transaction.JDBCTransactionFactory is mapped to
                        <classname>org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <literal>org.hibernate.transaction.JTATransactionFactory is mapped to
                        <classname>org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <literal>org.hibernate.transaction.CMTTransactionFactory is mapped to
                        <classname>org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory
                    </para>
                </listitem>
            </itemizedlist>
        </section>

    </section>


    <section>
        <title>Hibernate Transaction Usage
        <para>
            Hibernate uses JDBC connections and JTA resources directly, without adding any additional locking behavior.
            It is important for you to become familiar with the JBDC, ANSI SQL, and transaction isolation specification
            of your database management system.
        </para>
        <para>
            Hibernate does not lock objects in memory.  The behavior defined by the isolation level of your database
            transactions does not change when you use Hibernate.  The Hibernate
            <interfacename>org.hibernate.Session acts as a transaction-scoped cache providing
            repeatable reads for lookup by identifier and entity queries and not-reporting queries that return scalar
            values.
        </para>
    </section>

    <sidebar>
        <para>
            To reduce lock contention in the database, a database transaction needs to be as short as possible.  Long
            database transactions prevent your application from scaling to a highly-concurrent load.  Do not hold a
            database transaction open during end-user-level work, but open it after the end-user-level work is finished.
            This is concept is referred to as <literal>transactional write-behind.
        </para>
    </sidebar>


    <section>
        <title>Transaction Scopes

        <section id="session-per-operation">
            <title>Session-per-operation
            <subtitle>Antipatterns to avoid
      <para>
        <firstterm>Session-per-operation refers to the antipattern of opening and closing a
        <classname>Session for each database call in a single thread. It is also an antipattern in terms of
        database transactions. Group your database calls into a planned sequence. In the same way, do not auto-commit
        after every SQL statement in your application. Hibernate disables, or expects the application server to disable,
        auto-commit mode immediately. Database transactions are never optional. All communication with a database must
        be encapsulated by a transaction. Avoid auto-commit behavior for reading data, because many small transactions
        are unlikely to perform better than one clearly-defined unit of work, and are more difficult to maintain and
        extend.
      </para>
      <para>
        For more antipatterns to avoid, see <xref linkend="transaction-antipatterns" />.
      </para>
    </section>
    
    <section>
      <title>Session-per-request
      <subtitle>The typical desired pattern
      <para>
        The most common pattern in a multi-user client/server application is
        <firstterm>session-per-request. In this model, a client sends a request to the server, where the
        Hibernate persistence layer is running. Hibernate opens a new Session, and all database operations are executed
        in this unit of work. After the work is completed, and the server prepares the response for the client, the
        session is flushed and closed. Use a single database transaction to serve the clients request, starting and
        committing it when you open and close the Session. The relationship between the transaction and the Session is
        one-to-one.
      </para>
      <para>
        Hibernate provides built-in management of the <firstterm>current session to
        simplify the session-per-request pattern. Start a transaction to process a server request, and end the transaction
        before sending the response to the client. Common solutions include:
      </para>
      <itemizedlist>
        <listitem>
          <para>
            ServletFilter
          </para>
        </listitem>
        <listitem>
          <para>
            AOP interceptor with a pointcut on the service methods
          </para>
        </listitem>
        <listitem>
          <para>
            A proxy/interception container
          </para>
        </listitem>
      </itemizedlist>
      <para>
        An EJB container is a standardized way to implement cross-cutting aspects such as transaction demarcation on EJB
        session beans, declaratively with CMT. If you use programmatic transaction demarcation, use the <xref
        linkend="hibernate-transaction-api" />.
      </para>
      <para>
        To access a current session to process the request, call method
        <methodname>sessionFactory.getCurrentSession(). The returned Session is
        scoped to the current database transaction. You need to configure this for either resource-local or JTA
        environments
      </para>
      <para>
        You can extend the scope of a <classname>Session and database transaction until the view is
        rendered. This is especially useful in servlet applications that include a separate rendering phase after the
        request is processed. To extending the database transaction until view rendering, implement your own
        interceptor. This implementation is difficult if you rely on EJBs with container-managed transactions. A
        transaction is completed when an EJB method returns, before rendering of any view can start. Search the
        Hibernate forums for tips and examples relating to this <phrase>Open Session in View pattern.
      </para>
      <para>
        If <phrase>session-per-request does not seem well-suited for your application, refer to 
      <subtitle>An alternate pattern to session-per-request 
      <para>
        The <phrase>session-per-request pattern is not the only way of designing units of work. Many business
        processes require a whole series of interactions with the user that are interleaved with database accesses. In web
        and enterprise applications, it is not acceptable for a database transaction to span a user interaction. Consider
        the following example:
      </para>
      <procedure>
        <title>An example of a long-running conversation
        <step>
          <para>
            The first screen of a dialog opens. The data seen by the user is loaded in a particular
            <classname>Session and database transaction. The user is free to modify the objects.
          </para>
        </step>
        <step>
          <para>
            The user uses a UI element to save their work after five minutes of editing. The modifications are made
            persistent. The user also expects to have exclusive access to the data during the edit session.
          </para>
        </step>
      </procedure>
      <para>
        From the point of view of the user, this unit of work is a long-running conversation or application
        transaction. There are many ways to implement this in your application.
      </para>
      <para>
        A first naive implementation might keep the <classname>Session and database transaction open while the
        user is editing, using database-level locks to prevent other users from modifying the same data and to guarantee
        isolation and atomicity. This is an anti-pattern, because lock contention is a bottleneck which will prevent
        scalability in the future.
      </para>
      <para>
        Several database transactions are used to implement the conversation. In this case, maintaining isolation
        of business processes becomes the partial responsibility of the application tier. A single conversation usually
        spans several database transactions. It is atomic if only one of these database transactions, typically the last one,
        stores the updated data. All others only read data. A common way to receive this data is through a wizard-style
        dialog spanning several request/response cycles. Hibernate includes some features which make this easy to implement.
      </para>
      <informaltable>
        <tgroup cols="2">
          <tbody>
            <row>
              <entry>
                <para>
                  Automatic Versioning
                </para>
              </entry>
              <entry>
                <para>
                  Hibernate can perform automatic optimistic concurrency control for you. It can automatically detect if a
                  concurrent modification occurred during user think time. Check for this at the end of the conversation.
                </para>
              </entry>
            </row>
            <row>
              <entry>
                <para>
                  Detached Objects
                </para>
              </entry>
              <entry>
                <para>
                  If you decide to use the session-per-request pattern, all loaded instances will be in
                  the detached state during user think time. Hibernate allows you to reattach the objects and persist the
                  modifications. The pattern is called session-per-request-with-detached-objects. Automatic versioning is
                  used to isolate concurrent modifications.
                </para>
              </entry>
            </row>
            <row>
              <entry>
                <para>
                  Extended (or Long) Session
                </para>
              </entry>
              <entry>
                <para>
                  Extended (or Long) Session: the Hibernate Session can be disconnected from the underlying JDBC
                  connection after the database transaction has been committed and reconnected when a new client request
                  occurs. This pattern is known as session-per-conversation and makes even reattachment
                  unnecessary. Automatic versioning is used to isolate concurrent modifications and the Session will not
                  be allowed to be flushed automatically, but explicitly.
                </para>
              </entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
      <para>
        <phrase>Session-per-request-with-detached-objects and session-per-conversation each have
        advantages and disadvantages.
      </para>
    </section>

    <section>
      <title>Object identity
      <para>
        An application can concurrently access the same persistent state in two different Sessions. However, an instance
        of a persistent class is never shared between two <classname>Session instances. Therefore, two
        different notions of identity exist: Database identity and JVM identity.
      </para>
      <example>
        <title>Database identity
        <programlisting language="Java" role="JAVA">
      </example>
      <example>
        <title>JVM identity
        <programlisting language="Java" role="JAVA">
      </example>
      <para>
        For objects attached to a particular Session, the two notions are equivalent, and JVM identity for database
        identity is guaranteed by Hibernate. The application might concurrently access a business object with the same
        identity in two different sessions, the two instances are actually actually different, in terms of JVM
        identity. Conflicts are resolved using an optimistic approach and automatic versioning at flush/commit time.
      </para>
      <para>
        This approach places responsibility for conscurrency on Hibernate and the database. It also provides the best
        scalability, since expensive locking is not needed to guarantee identity in single-threaded units of work. The
        application does not need to synchronize on any business object, as long as it maintains a single thread per
        <classname>Session. Within a Session the application can safely use the
        <literal>== operator to compare objects.
      </para>
      <para>
        However, an application that uses the <literal>== operator outside of a Session
        may introduce problems.. If you put two detached instances into the same <classname>Set, they might
        use the same database identity, which means they represent the same row in the database. They would not be
        guaranteed to have the same JVM identity if they are in a detached state. Override the
        <methodname>equals and hashCode methods in persistant classes, so that
        they have their own notion of object equality. Never use the database identifier to implement equality. Instead,
        use a business key that is a combination of unique, typically immutable, attributes. The database identifier
        changes if a transient object is made persistent. If the transient instance, together with detached instances,
        is held in a <classname>Set, changing the hashcode breaks the contract of the
        <classname>Set. Attributes for business keys can be less stable than database primary keys. You only
        need to guarantee stability as long as the objects are in the same <classname>Set.This is not a
        Hibernate issue, but relates to Java's implementation of object identity and equality.
      </para>
      
    </section>

    <section id="transaction-antipatterns">
      <title>Problems and antipatterns
      <para>
        Avoid the anti-patterns session-per-user-session or session-per-application, for the most part. The reasons are
        outlined in <xref linkend="session-per-operation" />. In addition, keep the following points in mind when
        choosing patterns for your application.
      </para>
      <variablelist>
        <varlistentry>
          <term>A Session is not thread-safe.
          <listitem>
            <para>
              Resources, such as HTTP requests, session beans, or Swing workers, cause race conditions if a
              <classname>Session instance is shared. If you keep your Hibernate
              <classname>Session in your HttpSession, consider synchronizing access
              to your <classname>Http session. Otherwise, a reloaded application may use the same
              <classname>Session in two concurrently-running threads.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>If Hibernate throws an exception, you must rullback your database transaction and close the
          <classname>Session immediately.
          <listitem>
            <para>
              In addition to the above, if your Session is bound to the application, you must stop the
              application. Rolling back the database transaction does not put your business objects back into their
              state at the start of the transaction. The database state and the business objects will be out of
              sync. Since exceptions are not recoverable, this is typically not a problem. You must start over after
              rollback anyway.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>The Session caches every object that is in a persistent state.
          <listitem>
            <para>
              A persistent state refers to objects that are watched and checked for dirty state by Hibernate. If you
              keep the cache open for a long time or load too much data, it grows to fill available memory, causing an
              OutOfMemoryException.
            </para>
            <para>
              To solve this problem, you can call <methodname>clear() and evict()
              to manage the <classname>Session cache. Alternately, you can use a Stored Procedure if you
              need mass data operations. Keeping a <classname>Session open for the duration of a user
              session reduces the probability of stale data.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
  </section>

  
  <section id="hibernate-transaction-api">
    <title>Hibernate Transaction API (JTA)
    <para>
      If your persistence layer runs in an application server, such as behind EJB session beans, every datasource
      connection obtained by Hibernate is automatically part of the global JTA transaction. You can also install a
      standalone JTA implementation and use it without EJB. Hibernate offers two strategies for JTA integration.
    </para>
    <section>
      <title>Bean-managed transactions (BMT)
      <para>
        If you use bean-managed transactions (BMT), Hibernate tells the application server to start and end a BMT
        transaction if you use the Transaction API. The transaction management code is identical to the non-managed
        environment.
      </para>
      <example>
        <title>BMT idiom
        <programlisting language="Java" role="JAVA">
      </example>
      <para>
        Alternately, you can use a transaction-bound Session. If you need the
        <methodname>getCurrentSession() functionality for easy context propagation, use the JTA
        UserTransaction API directly.
      </para>
      <example>
        <title>BMT idiom with getCurrentSession()
        <programlisting language="Java" role="JAVA">
      </example>
    </section>
    
    <section>
      <title>Container-managed transactions (CMT)
      <para>
        With CMT, transaction demarcation is completed in session bean deployment descriptors, rather than
        programmatically.This reduces the amount of code.
      </para>
      <example>
        <title>CMT idiom
        <programlisting language="Java" role="JAVA">
      </example>
      <para>
        In a CMT/EJB, rollback happens automatically as well. An unhandled <systemitem>RuntimeException
        thrown by a session bean method tells the container to set the global transaction to rollback. You do not need
        to intervene, and you get automatic propagation of the <classname>Current
        <classname>Session bound to the transaction.
      </para>
      <para>
        When configuring Hibernate's transaction factory, choose
        <classname>org.hibernate.transaction.JTATransactionFactory if you use JTA directly (BMT), and
        <classname>org.hibernate.transaction.CMTTransactionFactory in a CMT session bean. Set the
        <varname>hibernate.transaction.manager_lookup_class property as well. Ensure that your
        <classname>hibernate.current_session_context_class is either unset, or is set to
        <literal>jta.
      </para>
      <para>
        The <methodname>getCurrentSession() method has one downside in a JTA environment. If you use it,
        after_statement connection release mode is also used by default. Due to a limitation of the JTA specification,
        Hibernate cannot automatically clean up any unclosed <classname>ScrollableResults or
        <classname>Iterator instances returned by scroll() or
        <methodname>iterate(). Release the underlying database cursor by calling
        <methodname>ScrollableResults.close() or Hibernate.close(Iterator)
        explicitly from a <systemitem>finally block. Try to avoid using scroll()
        or <methodname>iterate() from the JTA or CMT code.
      </para>
    </section>
  </section>
</chapter>

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate Transactions.xml source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.