updated transaction management stuff

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@6425 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Gavin King 2005-04-15 01:20:31 +00:00
parent a8b78969dc
commit 5731887aff
2 changed files with 94 additions and 60 deletions

View File

@ -1155,8 +1155,17 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<varlistentry> <varlistentry>
<term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term> <term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term>
<listitem> <listitem>
<para>delegates to JTA (if an existing transaction is underway, the <literal>Session</literal> <para>
performs its work in that context, otherwise a new transaction is started)</para> delegates to JTA (if an existing transaction is underway, the
<literal>Session</literal> performs its work in that context, otherwise
a new transaction is started)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>org.hibernate.transaction.CMTTransactionFactory</literal></term>
<listitem>
<para>delegates to a container managed JTA transaction</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -334,8 +334,8 @@
<para> <para>
However, it is often desirable 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 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 your deployment environment. This API is actually optional, but we strongly encourage its use
have to use it if database portability provided by Hibernate is all you need. unless you are in a CMT session bean.
</para> </para>
<para> <para>
@ -376,43 +376,12 @@
<para> <para>
If a Hibernate persistence layer runs in a non-managed environment, database connections If a Hibernate persistence layer runs in a non-managed environment, database connections
are either handled by Hibernate's pooling mechanism or provided by the developer (this are usually handled by Hibernate's pooling mechanism. The session/transaction handling
case has other implications, esp. with regard to caching): idiom looks like this:
</para> </para>
<programlisting><![CDATA[// Session sess = factory.openSession(myConnection); <programlisting><![CDATA[//Non-managed environment idiom
Session sess = factory.openSession(); Session sess = factory.openSession();
try {
// do some work
...
sess.flush();
sess.connection().commit();
}
catch (RuntimeException e) {
sess.connection().rollback();
throw e; // or display error message
}
finally {
sess.close();
}]]></programlisting>
<para>
Note that you will very likely never see this piece of code in a normal application;
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
container services whenever they are available. Exception handling is discussed later in
this chapter.
</para>
<para>
We recommend, even if persistence layer portability is not your primary concern, the
<literal>Transaction</literal> API:
</para>
<programlisting><![CDATA[Session sess = factory.openSession();
Transaction tx = null; Transaction tx = null;
try { try {
tx = sess.beginTransaction(); tx = sess.beginTransaction();
@ -431,22 +400,34 @@ finally {
}]]></programlisting> }]]></programlisting>
<para> <para>
Note that you don't have to <literal>flush()</literal> the <literal>Session</literal> You don't have to <literal>flush()</literal> the <literal>Session</literal> explicitly -
explicitly, the call to <literal>commit()</literal> automatically triggers the the call to <literal>commit()</literal> automatically triggers the synchronization.
synchronization. This piece of code is now portable and runs in non-managed and JTA
environments. See <xref linkend="configuration-optional-transactionstrategy"/> for
the configuration options of the <literal>Transaction</literal> API and how it can
be mapped to the underlying resource transaction system.
</para> </para>
<para> <para>
A call to <literal>close()</literal> marks the end of a session. The main implication A call to <literal>close()</literal> marks the end of a session. The main implication
of <literal>close()</literal> is that the JDBC connection will be relinquished by the session. of <literal>close()</literal> is that the JDBC connection will be relinquished by the
If you provided your own connection, <literal>close()</literal> returns a reference session.
to it, so you can manually close it or return it to the pool. Otherwise <literal>close()
</literal> returns it to the pool.
</para> </para>
<para>
This Java code is portable and runs in both non-managed and JTA environments.
</para>
<para>
You will very likely never see this idiom in business code in a normal application;
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
container services whenever they are available. Exception handling is discussed later in
this chapter.
</para>
<para>
Note that you should choose <literal>org.hibernate.transaction.JDBCTransaction</literal>.
</para>
</sect2> </sect2>
<sect2 id="transactions-demarcation-jta"> <sect2 id="transactions-demarcation-jta">
@ -455,28 +436,72 @@ finally {
<para> <para>
If your persistence layer runs in an application server (e.g. behind EJB session beans), If your persistence layer runs in an application server (e.g. behind EJB session beans),
transaction boundaries are defined in deployment descriptors. Every datasource connection transaction boundaries are defined in deployment descriptors. Every datasource connection
obtained by Hibernate will automatically be part of a global JTA transaction. Hibernate obtained by Hibernate will automatically be part of the global JTA transaction. Hibernate
simply joins this transaction, or if a particular session bean method has no mandatory simply joins this transaction, or if a particular session bean method has no mandatory
transaction, Hibernate will tell the application server to start and end a transaction transaction, Hibernate will tell the application server to start and end a BMT transaction
directly. (The latter should be considered a very rare case and is offered for consistency directly. So, for BMT, the session handling idiom is identical to case of a non-managed
reasons. Note that your container might not allow mixed CMT and BMT behavior.) environment:
</para>
<programlisting><![CDATA[//BMT idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some work
...
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}]]></programlisting>
<para>
Note that you should choose <literal>org.hibernate.transaction.JTATransaction</literal>
in a BMT session bean, and <literal>org.hibernate.transaction.CMTTransaction</literal>
in a CMT session bean.
</para> </para>
<para> <para>
If you set the properties <literal>hibernate.transaction.flush_before_completion</literal> If you set the properties <literal>hibernate.transaction.flush_before_completion</literal>
and <literal>hibernate.transaction.auto_close_session</literal> to <literal>true</literal>, and <literal>hibernate.transaction.auto_close_session</literal> to <literal>true</literal>,
Hibernate wil also automatically flush and close the <literal>Session</literal> for you. Hibernate will automatically flush and close the <literal>Session</literal> for you.
The only thing left is exception handling and rollback of the database transaction. The only thing left to rollback the transaction when an exception occurs. Fortunately, in
Fortunately, even this happens automatically, since an unhandled <literal>RuntimeException</literal> a CMT bean, even this happens automatically, since an unhandled <literal>RuntimeException</literal>
thrown by a session bean method tells the container to set the global transaction to thrown by a session bean method tells the container to set the global transaction to
rollback. rollback. <emphasis>This means you do not need to use the Hibernate
<literal>Transaction</literal> API at all in CMT.
</para>
<para>
If you don't want to bother passing your <literal>Session</literal> instance around, the
<literal>SessionFactory</literal> provides the <literal>getCurrentSession()</literal>
method, which returns a session that is bound to the JTA transaction context. This is the
easiest way to integrate Hibernate into an application! The "current" session always has
auto-flush and auto-close enabled (regardless of the above property settings). Our
session/transaction management idiom is reduced to this:
</para> </para>
<programlisting><![CDATA[//CMT idiom
Session sess = factory.getCurrentSession();
// do some work
...
]]></programlisting>
<para> <para>
In other words, all you have to do in a managed environment is to get a <literal>Session</literal> In other words, all you have to do in a managed environment is call
from the <literal>SessionFactory</literal> (usually bound to JNDI), do your data access <literal>SessionFactory.getCurrentSession()</literal>, do your data access work, and leave
work, and leave the rest to the container. Transaction boundaries are set declaratively in the rest to the container. Transaction boundaries are set declaratively in the deployment
the deployment descriptors of your session bean. descriptors of your session bean. The lifecycle of the session is completely managed by
Hibernate.
</para> </para>
</sect2> </sect2>