| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| <chapter id="jpa_overview_trans"> |
| <title> |
| Transaction |
| </title> |
| <indexterm zone="jpa_overview_trans"> |
| <primary> |
| transactions |
| </primary> |
| <seealso> |
| Transaction |
| </seealso> |
| </indexterm> |
| <para> |
| Transactions are critical to maintaining data integrity. They are used to group |
| operations into units of work that act in an all-or-nothing fashion. |
| Transactions have the following qualities: |
| </para> |
| <itemizedlist> |
| <listitem> |
| <para> |
| <indexterm> |
| <primary> |
| atomicity |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| atomicity |
| </secondary> |
| </indexterm> |
| <emphasis>Atomicity</emphasis>. Atomicity refers to the all-or-nothing property |
| of transactions. Either every data update in the transaction completes |
| successfully, or they all fail, leaving the datastore in its original state. A |
| transaction cannot be only partially successful. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| <indexterm> |
| <primary> |
| consistency |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| consistency |
| </secondary> |
| </indexterm> |
| <emphasis>Consistency</emphasis>. Each transaction takes the datastore from one |
| consistent state to another consistent state. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| <indexterm> |
| <primary> |
| isolation |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| isolation |
| </secondary> |
| </indexterm> |
| <emphasis>Isolation</emphasis>. Transactions are isolated from each other. When |
| you are reading persistent data in one transaction, you cannot "see" the changes |
| that are being made to that data in other transactions. Similarly, the updates |
| you make in one transaction cannot conflict with updates made in concurrent |
| transactions. The form of conflict resolution employed depends on whether you |
| are using pessimistic or optimistic transactions. Both types are described later |
| in this chapter. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| <indexterm> |
| <primary> |
| durability |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| durability |
| </secondary> |
| </indexterm> |
| <emphasis>Durability</emphasis>. The effects of successful transactions are |
| durable; the updates made to persistent data last for the lifetime of the |
| datastore. |
| </para> |
| </listitem> |
| </itemizedlist> |
| <para> |
| <indexterm> |
| <primary> |
| ACID |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| ACID |
| </secondary> |
| </indexterm> |
| Together, these qualities are called the ACID properties of transactions. To |
| understand why these properties are so important to maintaining data integrity, |
| consider the following example: |
| </para> |
| <para> |
| Suppose you create an application to manage bank accounts. The application |
| includes a method to transfer funds from one user to another, and it looks |
| something like this: |
| </para> |
| <programlisting> |
| public void transferFunds(User from, User to, double amnt) { |
| from.decrementAccount(amnt); |
| to.incrementAccount(amnt); |
| } |
| </programlisting> |
| <para> |
| Now suppose that user Alice wants to transfer 100 dollars to user Bob. No |
| problem; you simply invoke your <methodname>transferFunds</methodname> method, |
| supplying Alice in the <literal>from</literal> parameter, Bob in the <literal> |
| to</literal> parameter, and <literal>100.00</literal> as the <literal>amnt |
| </literal>. The first line of the method is executed, and 100 dollars is |
| subtracted from Alice's account. But then, something goes wrong. An unexpected |
| exception occurs, or the hardware fails, and your method never completes. |
| </para> |
| <para> |
| You are left with a situation in which the 100 dollars has simply disappeared. |
| Thanks to the first line of your method, it is no longer in Alice's account, and |
| yet it was never transferred to Bob's account either. The datastore is in an |
| inconsistent state. |
| </para> |
| <para> |
| The importance of transactions should now be clear. If the two lines of the |
| <methodname>transferFunds</methodname> method had been placed together in a |
| transaction, it would be impossible for only the first line to succeed. Either |
| the funds would be transferred properly or they would not be transferred at all, |
| and an exception would be thrown. Money could never vanish into thin air, and |
| the data store could never get into an inconsistent state. |
| </para> |
| <section id="jpa_overview_trans_types"> |
| <title> |
| Transaction Types |
| </title> |
| <indexterm zone="jpa_overview_trans_types"> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| types |
| </secondary> |
| </indexterm> |
| <para> |
| There are two major types of transactions: pessimistic transactions and |
| optimistic transactions. Each type has both advantages and disadvantages. |
| </para> |
| <para> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| pessimistic |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| pessimistic transactions |
| </primary> |
| <see> |
| transactions, pessimistic |
| </see> |
| </indexterm> |
| <indexterm> |
| <primary> |
| deadlock |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| Pessimistic transactions generally lock the datastore records they act on, |
| preventing other concurrent transactions from using the same data. This avoids |
| conflicts between transactions, but consumes database resources. Additionally, |
| locking records can result in <emphasis>deadlock</emphasis>, a situation in |
| which two transactions are both waiting for the other to release its locks |
| before completing. The results of a deadlock are datastore-dependent; usually |
| one transaction is forcefully rolled back after some specified timeout interval, |
| and an exception is thrown. |
| </para> |
| <para> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| datastore |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| datastore transactions |
| </primary> |
| <see> |
| transactions, datastore |
| </see> |
| </indexterm> |
| This document will often use the term <emphasis>datastore</emphasis> transaction |
| in place of <emphasis>pessimistic</emphasis> transaction. This is to acknowledge |
| that some datastores do not support pessimistic semantics, and that the exact |
| meaning of a non-optimistic JPA transaction is dependent on the datastore. Most |
| of the time, a datastore transaction is equivalent to a pessimistic transaction. |
| </para> |
| <para> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| optimistic |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| optimistic transactions |
| </primary> |
| <see> |
| transactions, optimistic |
| </see> |
| </indexterm> |
| Optimistic transactions consume less resources than pessimistic/datastore |
| transactions, but only at the expense of reliability. Because optimistic |
| transactions do not lock datastore records, two transactions might change the |
| same persistent information at the same time, and the conflict will not be |
| detected until the second transaction attempts to flush or commit. At this time, |
| the second transaction will realize that another transaction has concurrently |
| modified the same records (usually through a timestamp or versioning system), |
| and will throw an appropriate exception. Note that optimistic transactions still |
| maintain data integrity; they are simply more likely to fail in heavily |
| concurrent situations. |
| </para> |
| <para> |
| Despite their drawbacks, optimistic transactions are the best choice for most |
| applications. They offer better performance, better scalability, and lower risk |
| of hanging due to deadlock. |
| </para> |
| <note> |
| <para> |
| OpenJPA uses optimistic semantics by default, but supports both optimistic and |
| datastore transactions. OpenJPA also offers advanced locking and versioning APIs |
| for fine-grained control over database resource allocation and object |
| versioning. See <xref linkend="ref_guide_locking"/> of the Reference Guide for |
| details on locking. <xref linkend="jpa_overview_meta_version"/> |
| of this document covers standard object versioning, while |
| <xref linkend="ref_guide_mapping_jpa"/> of the Reference Guide discusses |
| additional versioning strategies available in OpenJPA. |
| </para> |
| </note> |
| </section> |
| <section id="jpa_overview_trans_local"> |
| <title> |
| The EntityTransaction Interface |
| </title> |
| <indexterm zone="jpa_overview_trans_local"> |
| <primary> |
| Transaction |
| </primary> |
| <seealso> |
| transactions |
| </seealso> |
| </indexterm> |
| <mediaobject> |
| <imageobject> |
| <!-- PNG image data, 193 x 157 (see README) --> |
| <imagedata fileref="img/jpa-transaction.png" width="129px"/> |
| |
| </imageobject> |
| </mediaobject> |
| <para> |
| JPA integrates with your container's <emphasis>managed</emphasis> transactions, |
| allowing you to use the container's declarative transaction demarcation and its |
| Java Transaction API (JTA) implementation for transaction management. Outside of |
| a container, though, you must demarcate transactions manually through JPA. The |
| <classname>EntityTransaction</classname> interface controls unmanaged |
| transactions in JPA. |
| </para> |
| <programlisting> |
| public void begin(); |
| public void commit(); |
| public void rollback(); |
| </programlisting> |
| <para> |
| <indexterm> |
| <primary> |
| Transaction |
| </primary> |
| <secondary> |
| demarcation |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| transactions |
| </primary> |
| <secondary> |
| demarcating |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| Transaction |
| </primary> |
| <secondary> |
| begin |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| Transaction |
| </primary> |
| <secondary> |
| commit |
| </secondary> |
| </indexterm> |
| <indexterm> |
| <primary> |
| Transaction |
| </primary> |
| <secondary> |
| rollback |
| </secondary> |
| </indexterm> |
| The <methodname>begin</methodname>, <methodname>commit</methodname>, and |
| <methodname>rollback</methodname> methods demarcate transaction boundaries. The |
| methods should be self-explanatory: <methodname>begin</methodname> starts a |
| transaction, <methodname>commit</methodname> attempts to commit the |
| transaction's changes to the datastore, and <methodname>rollback</methodname> |
| aborts the transaction, in which case the datastore is "rolled back" to its |
| previous state. JPA implementations will automatically roll back transactions if |
| any exception is thrown during the commit process. |
| </para> |
| <para> |
| Unless you are using an extended persistence context, committing or rolling back |
| also ends the persistence context. All managed entities will be detached from the |
| <classname>EntityManager</classname>. |
| </para> |
| <programlisting> |
| public boolean isActive(); |
| </programlisting> |
| <para> |
| <indexterm> |
| <primary> |
| Transaction |
| </primary> |
| <secondary> |
| isActive |
| </secondary> |
| </indexterm> |
| Finally, the <methodname>isActive</methodname> method returns <literal>true |
| </literal> if the transaction is in progress (<methodname>begin</methodname> |
| has been called more recently than <methodname>commit</methodname> or |
| <methodname>rollback</methodname>), and <literal>false</literal> otherwise. |
| </para> |
| <example id="jpa_overview_trans_group"> |
| <title> |
| Grouping Operations with Transactions |
| </title> |
| <programlisting> |
| public void transferFunds(EntityManager em, User from, User to, double amnt) { |
| // note: it would be better practice to move the transaction demarcation |
| // code out of this method, but for the purposes of example... |
| Transaction trans = em.getTransaction(); |
| trans.begin(); |
| try |
| { |
| from.decrementAccount(amnt); |
| to.incrementAccount(amnt); |
| trans.commit(); |
| } |
| catch (RuntimeException re) |
| { |
| if (trans.isActive()) |
| trans.rollback(); // or could attempt to fix error and retry |
| throw re; |
| } |
| } |
| </programlisting> |
| </example> |
| </section> |
| </chapter> |