Modified: incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_sqlquery.xml URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_sqlquery.xml?rev=434517&r1=434516&r2=434517&view=diff ============================================================================== --- incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_sqlquery.xml (original) +++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_sqlquery.xml Thu Aug 24 13:41:12 2006 @@ -1,135 +1,195 @@ - - <chapter id="jpa_overview_sqlquery"> - <title>SQL Queries</title> - <indexterm zone="jpa_overview_sqlquery"> - <primary>SQL queries</primary> - <seealso>Query</seealso> - </indexterm> - <indexterm> - <primary>Query</primary> - <secondary>SQL</secondary> - <see>SQL queries</see> - </indexterm> - <indexterm> - <primary>SQL</primary> - <secondary>queries</secondary> - <see>SQL queries</see> - </indexterm> - <indexterm> - <primary>Native</primary> - <secondary>queries</secondary> - <see>SQL queries</see> - </indexterm> - <para> - JPQL is a powerful query language, but there are times when it is - not enough. Maybe you're migrating a JDBC application to JPA - on a strict deadline, and you don't have time to translate your existing - SQL selects to JPQL. Or maybe a certain query requires - database-specific SQL your JPA implementation doesn't support. - Or maybe your DBA has spent hours crafting the perfect select statement - for a query in your application's critical path. Whatever the reason, SQL - queries can remain an essential part of an application. - </para> - <para> - You are probably familiar with executing SQL queries by obtaining a - <classname>java.sql.Connection</classname>, using the JDBC APIs to create - a <classname>Statement</classname>, and executing that <classname>Statement - </classname> to obtain a <classname>ResultSet</classname>. And of course, - you are free to continue using this low-level approach to SQL execution in - your JPA applications. However, JPA also supports executing SQL queries - through the <classname>javax.persistence.Query</classname> - interface introduced in <xref linkend="jpa_overview_query"/>. - Using a JPA SQL query, you can retrieve either persistent objects - or projections of column values. The following sections detail each use. - </para> - <section id="jpa_overview_sqlquery_create"> - <title>Creating SQL Queries</title> +<chapter id="jpa_overview_sqlquery"> + <title> + SQL Queries + </title> + <indexterm zone="jpa_overview_sqlquery"> + <primary> + SQL queries + </primary> + <seealso> + Query + </seealso> + </indexterm> + <indexterm> + <primary> + Query + </primary> + <secondary> + SQL + </secondary> + <see> + SQL queries + </see> + </indexterm> + <indexterm> + <primary> + SQL + </primary> + <secondary> + queries + </secondary> + <see> + SQL queries + </see> + </indexterm> + <indexterm> + <primary> + Native + </primary> + <secondary> + queries + </secondary> + <see> + SQL queries + </see> + </indexterm> + <para> +JPQL is a powerful query language, but there are times when it is not enough. +Maybe you're migrating a JDBC application to JPA on a strict deadline, and you +don't have time to translate your existing SQL selects to JPQL. Or maybe a +certain query requires database-specific SQL your JPA implementation doesn't +support. Or maybe your DBA has spent hours crafting the perfect select statement +for a query in your application's critical path. Whatever the reason, SQL +queries can remain an essential part of an application. + </para> + <para> +You are probably familiar with executing SQL queries by obtaining a <classname> +java.sql.Connection</classname>, using the JDBC APIs to create a <classname> +Statement</classname>, and executing that <classname>Statement</classname> to +obtain a <classname>ResultSet</classname>. And of course, you are free to +continue using this low-level approach to SQL execution in your JPA +applications. However, JPA also supports executing SQL queries through the +<classname>javax.persistence.Query</classname> interface introduced in +<xref linkend="jpa_overview_query"></xref>. Using a JPA SQL query, you can +retrieve either persistent objects or projections of column values. The +following sections detail each use. + </para> + <section id="jpa_overview_sqlquery_create"> + <title> + Creating SQL Queries + </title> <indexterm zone="jpa_overview_sqlquery_create"> - <primary>SQL queries</primary> - <secondary>creating</secondary> + <primary> + SQL queries + </primary> + <secondary> + creating + </secondary> </indexterm> <para> - The <classname>EntityManager</classname> has two factory methods - suitable for creating SQL queries: - </para> - <programlisting format="linespecific"> +The <classname>EntityManager</classname> has two factory methods suitable for +creating SQL queries: + </para> +<programlisting> public Query createNativeQuery (String sqlString, Class resultClass); public Query createNativeQuery (String sqlString, String resultSetMapping); </programlisting> <para> - The first method is used to create a new <classname>Query</classname> - instance that will return instances of the specified class. - </para> - <para> - The second method uses a <literal>SqlResultSetMapping</literal> - to determine the type of object or objects to return. - The example below shows these methods in action. - </para> +The first method is used to create a new <classname>Query</classname> instance +that will return instances of the specified class. + </para> + <para> +The second method uses a <literal>SqlResultSetMapping</literal> to determine the +type of object or objects to return. The example below shows these methods in +action. + </para> <example id="jpa_overview_sqlquery_createex"> - <title>Creating a SQL Query</title> - <programlisting format="linespecific"> + <title> + Creating a SQL Query + </title> +<programlisting> EntityManager em = ...; Query query = em.createNativeQuery ("SELECT * FROM MAG", Magazine.class); processMagazines (query.getResultList ()); </programlisting> </example> <note> - <para><indexterm><primary>SQL queries</primary><secondary>stored procedures</secondary></indexterm><indexterm><primary>stored procedures</primary><secondary>as queries</secondary><seealso>Query</seealso></indexterm> - In addition to SELECT statements, OpenJPA supports stored procedure - invocations as SQL queries. OpenJPA will assume any SQL that does - not begin with the <literal>SELECT</literal> keyword (ignoring - case) is a stored procedure call, and invoke it as such at the - JDBC level. - </para> + <para> + <indexterm> + <primary> + SQL queries + </primary> + <secondary> + stored procedures + </secondary> + </indexterm> + <indexterm> + <primary> + stored procedures + </primary> + <secondary> + as queries + </secondary> + <seealso> + Query + </seealso> + </indexterm> +In addition to SELECT statements, OpenJPA supports stored procedure invocations +as SQL queries. OpenJPA will assume any SQL that does not begin with the +<literal>SELECT</literal> keyword (ignoring case) is a stored procedure call, +and invoke it as such at the JDBC level. + </para> </note> - </section> - <section id="jpa_overview_sqlquery_obj"> - <title>Retrieving Persistent Objects with SQL</title> + </section> + <section id="jpa_overview_sqlquery_obj"> + <title> + Retrieving Persistent Objects with SQL + </title> <indexterm zone="jpa_overview_sqlquery_obj"> - <primary>SQL queries</primary> - <secondary>retrieving persistent objects</secondary> + <primary> + SQL queries + </primary> + <secondary> + retrieving persistent objects + </secondary> </indexterm> <indexterm zone="jpa_overview_sqlquery_obj"> - <primary>persistent objects</primary> - <secondary>retrieving with SQL</secondary> - <seealso>SQL queries</seealso> + <primary> + persistent objects + </primary> + <secondary> + retrieving with SQL + </secondary> + <seealso> + SQL queries + </seealso> </indexterm> <para> - When you give a SQL <classname>Query</classname> a candidate class, it - will return persistent instances of that class. At a minimum, your - SQL must select the - class' primary key columns, discriminator column (if mapped), and - version column (also if mapped). The JPA runtime uses the values - of the primary key columns to construct each result object's identity, - and possibly to match it with a persistent object already in the - <classname>EntityManager</classname>'s cache. When an object is - not already cached, the - implementation creates a new object to represent the current result - row. It might use the discriminator column value to make sure it - constructs an object of the correct subclass. Finally, the query - records available version column data for use in optimistic concurrency - checking, should you later change the result object and flush it back - to the database. - </para> - <para> - Aside from the primary key, discriminator, and version columns, any - columns you select are used to populate the persistent fields of each - result object. JPA implementations will compete on how effectively - they map your selected data to your persistent instance fields. - </para> - <para> - Let's make the discussion above concrete with an example. It uses - the following simple mapping between a class and the database: - </para> +When you give a SQL <classname>Query</classname> a candidate class, it will +return persistent instances of that class. At a minimum, your SQL must select +the class' primary key columns, discriminator column (if mapped), and version +column (also if mapped). The JPA runtime uses the values of the primary key +columns to construct each result object's identity, and possibly to match it +with a persistent object already in the <classname>EntityManager</classname>'s +cache. When an object is not already cached, the implementation creates a new +object to represent the current result row. It might use the discriminator +column value to make sure it constructs an object of the correct subclass. +Finally, the query records available version column data for use in optimistic +concurrency checking, should you later change the result object and flush it +back to the database. + </para> + <para> +Aside from the primary key, discriminator, and version columns, any columns you +select are used to populate the persistent fields of each result object. JPA +implementations will compete on how effectively they map your selected data to +your persistent instance fields. + </para> + <para> +Let's make the discussion above concrete with an example. It uses the following +simple mapping between a class and the database: + </para> <mediaobject> - <imageobject> -<!-- PNG image data, 320 x 149 (see README) --> - <imagedata fileref="img/sqlquery-model.png" width="213px"/> - </imageobject> + <imageobject> + <!-- PNG image data, 320 x 149 (see README) --> + <imagedata fileref="img/sqlquery-model.png" width="213px"> + </imagedata> + </imageobject> </mediaobject> <example id="jpa_overview_sqlquery_objex"> - <title>Retrieving Persistent Objects</title> - <programlisting format="linespecific"> + <title> + Retrieving Persistent Objects + </title> +<programlisting> Query query = em.createNativeQuery ("SELECT ISBN, TITLE, PRICE, " + "VERS FROM MAG WHERE PRICE > 5 AND PRICE < 10", Magazine.class); List<Magazine> results = query.getResultList (); @@ -138,13 +198,15 @@ </programlisting> </example> <para> - The query above works as advertised, but isn't very flexible. Let's - update it to take in parameters for the minimum and maximum price, - so we can reuse it to find magazines in any price range: - </para> +The query above works as advertised, but isn't very flexible. Let's update it to +take in parameters for the minimum and maximum price, so we can reuse it to find +magazines in any price range: + </para> <example id="jpa_overview_sqlquery_obj_paramex"> - <title>SQL Query Parameters</title> - <programlisting format="linespecific"> + <title> + SQL Query Parameters + </title> +<programlisting> Query query = em.createNativeQuery ("SELECT ISBN, TITLE, PRICE, " + "VERS FROM MAG WHERE PRICE > ?1 AND PRICE < ?2", Magazine.class); @@ -156,183 +218,28 @@ processMagazine (mag); </programlisting> </example> - <para><indexterm><primary>SQL queries</primary><secondary>parameters</secondary></indexterm><indexterm><primary>parameters</primary><secondary>in SQL queries</secondary><seealso>SQL queries</seealso></indexterm> - Like JDBC prepared statements, SQL queries represent parameters with - question marks, but are followed by an integer to represent its - index. - </para> - </section> -<!-- - <section id="jpa_overview_sqlquery_proj"> - <title>SQL Projections</title> - <indexterm zone="jpa_overview_sqlquery_proj"> - <primary>SQL queries</primary> - <secondary>projections</secondary> - </indexterm> - <indexterm zone="jpa_overview_sqlquery_proj"> - <primary>projections</primary> - <secondary>of column data</secondary> - <seealso>SQL queries</seealso> - </indexterm> - <para> - SQL queries without a candidate class are treated as projections of - column data. If you select a single column, the query returns - a list of <classname>Object</classname>s. If you select multiple - columns, it returns a list of <classname>Object[]</classname>s. - In either case, each column value is obtained using the - <methodname>java.sql.ResultSet.getObject</methodname> method. The - following example demonstrates a query for the values of the - <literal>ISBN</literal> and <literal>VERS</literal> columns of all - <literal>MAG</literal> table records, using the data model we - defined in <xref linkend="jpa_overview_sqlquery_obj"/>. - </para> - <example id="jpa_overview_sqlquery_projex"> - <title>Column Projection</title> -<programlisting> -Query query = em.newQuery ("javax.persistence.query.SQL", - "SELECT ISBN, VERS FROM MAG"); -List results = query.getResultList (); -for (Iterator itr = results.iterator (); itr.hasNext ();) -{ - Object[] data = (Object[]) results.next (); - processISBNAndVersion (data[0], data[1]); -} -</programlisting> - <para> - Notice that in the code above, we did not set a candidate class. - Therefore, the query is treated as a projection. - </para> - </example> - <para> - <indexterm> - <primary>SQL queries</primary> - <secondary>result class</secondary> - </indexterm> - Our discussion of JPQL query result classes in - <xref linkend="jpa_overview_query_resultcls"/> also - applies to SQL queries. As with JPQL queries, SQL queries can - automatically pack their results into objects of a specified type. - JPA uses the <methodname>java.sql.ResultSetMetaData.getColumnLabel - </methodname> method to match each column alias to the result class' - public fields and JavaBean setter methods. Here is a modification of - our example above that packs the selected column values into JavaBean - instances. - </para> - <example id="jpa_overview_sqlquery_proj_labelex"> - <title>Result Class</title> -<programlisting> -public class Identity -{ - private String id; - private int versionNumber; - - public void setId (String id) - { - this.id = id; - } - - public String getId () - { - return id; - } - - public void setVersionNumber (int versionNumber) - { - this.versionNumber = versionNumber; - } - - public int getVersionNumber () - { - return versionNumber; - } -} - -Query query = em.createNativeQuery ("javax.persistence.query.SQL", - "SELECT ISBN AS id, VERS AS versionNumber FROM MAG", Identity.class); -List results = query.getResultList (); -for (Iterator itr = results.iterator (); itr.hasNext ();) - processIdentity ((Identity) itr.next ()); -</programlisting> - </example> - </section> - <section id="jpa_overview_sqlquery_named"> - <title>Named SQL Queries</title> - <indexterm zone="jpa_overview_sqlquery_named"> - <primary>SQL queries</primary> - <secondary>named</secondary> - <see>named queries</see> - </indexterm> - <indexterm zone="jpa_overview_sqlquery_named"> - <primary>named queries</primary> - <secondary>SQL</secondary> - </indexterm> - <para> - We discussed how to write named JPQL queries in - <xref linkend="jpa_overview_query_named"/>. Named queries, however, - are not limited to JPQL. By setting the <literal>query</literal> - element's <literal>language</literal> attribute to <literal> - javax.persistence.query.SQL</literal>, you can define a named SQL query. A - named SQL query within a <literal>class</literal> element queries for - instances of that class; a named SQL query outside of a <literal>class - </literal> element acts as a column data projection. - </para> - <example id="jpa_overview_sqlquery_namedex"> - <title>Named SQL Queries</title> -<programlisting> -<![CDATA[<?xml version="1.0"?> -<jdoquery> - <query name="salesReport" language="javax.persistence.query.SQL"> - SELECT TITLE, PRICE * COPIES FROM MAG - </query> - <package name="org.mag"> - <class name="Magazine"> - <query name="findByTitle" language="javax.persistence.query.SQL"> - SELECT * FROM MAG WHERE TITLE = ? - </query> - </class> - </package> -</jdoquery>]]> -</programlisting> - <para> - The <literal>salesReport</literal> query above returns the title - and revenue generated for each <classname>Magazine</classname>. - Because it is a projection, it does not have a candidate class, and - so we specify it at the root level. - </para> - <para> - The <literal>findByTitle</literal> query returns the <classname> - Magazine</classname> with the title given on execution. The code - below executes both queries. - </para> -<programlisting> -EntityManager em = ...; -Query query = em.newNamedQuery (null, "salesReport"); -List sales = query.getResultList (); -for (Iterator itr = sales.iterator (); itr.hasNext ();) -{ - Object[] salesData = (Object[]) itr.next (); - processSalesData ((String) salesData[0], (Number) salesData[1]); -} - -query = em.newNamedQuery (Magazine.class, "findByTitle"); -query.setUnique (true); -Magazine jdj = (Magazine) query.execute ("JDJ"); -</programlisting> - </example> - </section> - <section id="jpa_overview_sqlquery_conclusion"> - <title>Conclusion</title> - <para> - If you've used relational databases extensively, you might be tempted - to perform all your JPA queries with SQL. Try to resist this - temptation. SQL queries tie your application to the particulars of - your current table model and database vendor. If you stick with JPQL, - on the other hand, you can port your application to other schemas and - database vendors without any changes to your code. Additionally, - most JPA implementations already produce highly optimized SQL from - your JPQL filters, and many are able to cache JPQL query results - for added performance. - </para> - </section> - --> - </chapter> + <para> + <indexterm> + <primary> + SQL queries + </primary> + <secondary> + parameters + </secondary> + </indexterm> + <indexterm> + <primary> + parameters + </primary> + <secondary> + in SQL queries + </secondary> + <seealso> + SQL queries + </seealso> + </indexterm> +Like JDBC prepared statements, SQL queries represent parameters with question +marks, but are followed by an integer to represent its index. + </para> + </section> +</chapter>
Modified: incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_trans.xml URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_trans.xml?rev=434517&r1=434516&r2=434517&view=diff ============================================================================== --- incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_trans.xml (original) +++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_trans.xml Thu Aug 24 13:41:12 2006 @@ -1,214 +1,403 @@ - - <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> +<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> + <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> + <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> + <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> + <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 format="linespecific"> + </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> + <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> + <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> +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"/> and - <xref linkend="ref_guide_lock_groups"/> of the Reference Guide for - details on locking. <xref linkend="jpa_overview_meta_version"/> - of this document covers standard object versioning. - <!-- ### EJBDOC : link additional strats when available from JPA --> - </para> + <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"></xref> and +<xref linkend="ref_guide_lock_groups"></xref> of the Reference Guide for details +on locking. <xref linkend="jpa_overview_meta_version"></xref> +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_ejb3"> - <title>The EntityTransaction Interface</title> - <indexterm zone="jpa_overview_trans_ejb3"> - <primary>Transaction</primary> - <seealso>transactions</seealso> + </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> + <imageobject> + <!-- PNG image data, 193 x 157 (see README) --> + <imagedata fileref="img/jpa-transaction.png" width="129px"> + </imagedata> + </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 format="linespecific"> +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 entites - will be detached from the <classname>EntityManager</classname>. - </para> - <programlisting format="linespecific"> + <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 entites 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> + <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 format="linespecific"> + <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 @@ -230,5 +419,5 @@ } </programlisting> </example> - </section> - </chapter> + </section> +</chapter>
