You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mp...@apache.org on 2006/08/22 23:28:55 UTC
svn commit: r433761 [7/18] - in /incubator/openjpa/trunk/openjpa-project: ./
src/doc/manual/
Added: incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_tutorials.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_tutorials.xml?rev=433761&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_tutorials.xml (added)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_tutorials.xml Tue Aug 22 14:28:53 2006
@@ -0,0 +1,1704 @@
+
+ <chapter id="jpa_tutorials">
+ <title>JPA Tutorials</title>
+ <section id="jpa_tutorials_intro">
+ <title>OpenJPA Tutorials</title>
+ <para>
+ These tutorials provide step-by-step examples of how to use various
+ facets of the OpenJPA system. They assume a general knowledge
+ of JPA and Java. For more information on these subjects, see
+ the following URLs:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <ulink url="http://java.sun.com/">Sun's Java site</ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <link linkend="jpa_overview_intro">JPA Overview Document</link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <link linkend="jpa_resources">Links to JPA</link>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <section id="jpa_tutorial_requirements">
+ <title>Tutorial Requirements</title>
+ <para>
+ These tutorials require that JDK 1.5 or greater be installed
+ on your computer, and that <literal>java</literal> and
+ <literal>javac</literal> are in your <literal>PATH</literal> when
+ you open a command shell.
+ </para>
+ </section>
+ </section>
+ <section id="jpa_tutorial">
+ <title>OpenJPA Tutorial</title>
+ <para>
+ In this tutorial you will become familiar with the basic tools and
+ development processes under OpenJPA by creating a simple JPA application.
+ </para>
+ <section id="jpa_tutorial_chapter1">
+ <title>The Pet Shop</title>
+ <para>
+ Imagine that you have decided to create a software toolkit to be used
+ by pet shop operators. This toolkit must provide a number of solutions
+ to common problems encountered at pet shops. Industry analysts indicate
+ that the three most desired features are inventory maintenance,
+ inventory growth simulation, and behavioral analysis. Not one to
+ question the sage advice of experts, you choose to attack these three
+ problems first.
+ </para>
+ <para>
+ According to the aforementioned experts, most pet shops focus on three
+ types of animals only: dogs, rabbits, and snakes. This ontology
+ suggests the following class hierarchy:
+ </para>
+ <para>
+ <screen format="linespecific">
+ Animal
+ ^
+ |
+ +--------------------+
+ | | |
+ Dog Rabbit Snake
+ </screen>
+ </para>
+ <section id="jpa_tutorial_files">
+ <title>Included Files</title>
+ <para>
+ We have provided an implementation of <classname>Animal</classname>
+ and <classname>Dog</classname> classes, plus some helper classes
+ and files to create the initial schema and populate the database
+ with some sample dogs. Let's take a closer look at these classes.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="../../../tutorial/persistence/AnimalMaintenance.java"><classname>
+ tutorial.persistence.AnimalMaintenance</classname></ulink>:
+ Provides some utility methods for examining and
+ manipulating the animals stored in the database. We will
+ fill in method definitions in
+ <xref linkend="jpa_tutorial_chapter3"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><ulink url="../../../tutorial/persistence/Animal.java"><classname>tutorial.persistence.Animal</classname></ulink>:
+ This is the superclass of all animals that this pet store
+ software can handle.
+ </para>
+ </listitem>
+ <listitem>
+ <para><ulink url="../../../tutorial/persistence/Dog.java"><classname>tutorial.persistence.Dog</classname></ulink>:
+ Contains data and methods specific to dogs.
+ </para>
+ </listitem>
+ <listitem>
+ <para><ulink url="../../../tutorial/persistence/Rabbit.java"><classname>tutorial.persistence.Rabbit</classname></ulink>:
+ Contains data and
+ methods specific to rabbits. It will be used in
+ <xref linkend="jpa_tutorial_chapter4"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><ulink url="../../../tutorial/persistence/Snake.java"><classname>tutorial.persistence.Snake</classname></ulink>:
+ Contains data and
+ methods specific to snakes. It will be used in
+ <xref linkend="jpa_tutorial_chapter5"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><ulink url="../../../META-INF/persistence.xml"><filename>../../META-INF/persistence.xml</filename></ulink>:
+ This XML file contains OpenJPA-specific and standard JPA
+ configuration settings.
+ </para>
+ <para>
+ It is important to load all persistent entity classes at
+ startup so that OpenJPA can match database discriminator values
+ to entity classes. Often this happens automatically.
+ Some parts of this tutorial, however, do require that all
+ entity classes be loaded explicitly. The JPA
+ standard includes persistent class listings in its XML
+ configuration format. Add the following lines to <filename>
+ ../../META-INF/persistence.xml</filename> between the
+ <literal><provider></literal> and the
+ <literal><properties></literal> elements:
+ </para>
+ <programlisting format="linespecific">
+<class>tutorial.persistence.Animal</class>
+<class>tutorial.persistence.Dog</class>
+</programlisting>
+ </listitem>
+ <listitem>
+ <para><ulink url="../../../tutorial/persistence/solutions"><filename>solutions</filename></ulink>: The solutions
+ directory contains the complete solutions to this tutorial,
+ including finished versions of the
+ <filename>.java</filename> files listed above.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="jpa_tutorial_utilities">
+ <title>Important Utilities</title>
+ <itemizedlist>
+ <listitem>
+ <para><command>java</command>: Runs main methods in specified
+ Java classes.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>javac</command>: Compiles <filename>.java
+ </filename> files into <filename>.class</filename>
+ files that can be executed by <command>java</command>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><indexterm><primary>openjpac</primary></indexterm><command>openjpac</command>:
+ Runs the OpenJPA enhancer against the specified
+ classes. More information is available in
+ <xref linkend="ref_guide_pc_enhance"/> of the Reference
+ Guide.
+ </para>
+ </listitem>
+ <listitem>
+ <para><indexterm><primary>mappingtool</primary></indexterm><command>mappingtool</command>: A
+ utility that can be used to create and maintain the
+ object-relational mappings and schema of all persistent
+ classes in a JDBC-compliant datastore. This functionality
+ allows the underlying mappings and schema to be easily
+ kept up-to-date with the Java classes in the system. See
+ <xref linkend="ref_guide_mapping"/>
+ of the Reference Guide for more information.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+ <section id="jpa_tutorial_chapter2">
+ <title>Getting Started</title>
+ <para>
+ Let's compile the initial classes and see them in action. To do
+ so, we must compile the <filename>.java</filename> files, as we would
+ with any Java project, and then pass the resulting classes through
+ the OpenJPA enhancer:
+ </para>
+ <note>
+ <para><indexterm><primary>CLASSPATH</primary></indexterm>
+ Be sure that your <envar>CLASSPATH</envar> is set correctly.
+ Note that your OpenJPA
+ install directory should be in the <envar>CLASSPATH</envar>, as
+ the tutorial classes are located in the <literal>
+ tutorial/persistence</literal> directory under your OpenJPA install
+ directory, and are in the <literal>tutorial.persistence</literal>
+ package.
+ </para>
+ </note>
+ <orderedlist>
+ <listitem>
+ <para>
+ Make sure you are in the <filename>
+ tutorial/persistence</filename>
+ directory. All examples throughout the tutorial assume that
+ you are in this directory.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Examine <filename>Animal.java</filename>,
+ <filename>Dog.java</filename>, and
+ <filename>SeedDatabase.java</filename>
+ </para>
+ <para>
+ These files are good examples of the simplicity JPA
+ engenders. As noted earlier, persisting an object or
+ manipulating an object's persistent data requires almost no
+ JPA-specific code.
+ For a very simple example of creating persistent objects,
+ please see the <literal>seed</literal> method of
+ <filename>SeedDatabase.java</filename>. Note the objects are
+ created with normal Java
+ constructors. The files <filename>Animal.java</filename> and
+ <filename>Dog.java</filename> are also good examples of
+ how JPA allows you to manipulate persistent data
+ without writing any specific JPA code, by providing
+ simple annotations.
+ </para>
+ <para>
+ Let's take a look at the <filename>Animal.java</filename> file.
+ Notice that the class is a Plain Old Java Object (POJO), with
+ several annotations describing how the class is mapped into
+ a relational database. First, let's examine the class level
+ annotations:
+ </para>
+ <programlisting format="linespecific">
+@Entity(name="Animal")
+@Table(name="JPA_TUT_ANIMAL")
+@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn(name="SPECIES", length=100)
+public abstract class Animal
+{
+ ...
+}
+</programlisting>
+ <para>
+ The annotations serve to map the class into the database. For
+ more information on these and other annotations, see
+ <xref linkend="jpa_overview_meta"/> and
+ <xref linkend="jpa_overview_mapping"/>.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para><command>@Entity</command>: This annotation indicates
+ that instances of this class may be persistent entities.
+ The value of the <command>name</command> attribute is
+ the entity name, and is used in queries, etc.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>@Table</command>: This annotation is used
+ to map the entity to a primary table. The value of the
+ <command>name</command> attribute specifies the name
+ of the relational table to use as the primary table.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>@Inheritance</command>: When multiple classes
+ in an inheritance hierarchy are persistent entity types,
+ it is important to describe how the inheritance
+ hierarchy is mapped. Setting the value of the
+ <command>strategy</command> attribute to
+ <command>InheritanceType.SINGLE_TABLE</command>
+ indicates that the primary table for all subclasses
+ shall be the same table as for the superclass.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>@DiscriminatorColumn</command>: With a
+ <command>SINGLE_TABLE</command> inheritance mapping
+ strategy, instances of multiple classes will be stored
+ in the same table. This annotation describes a column
+ in that table that is used to determine the type of
+ an instance whose data is stored in a particular row.
+ The <command>name</command> attribute is the name of
+ the column, and the <command>length</command> attribute
+ indicates the size of the column. By default, the
+ unqualified class name for the instance is stored
+ in the discriminator column. To store a different
+ value for a type, use the <command>@DiscriminatorValue
+ </command> annotation.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Let's take a look at our class' field annotations.
+ We have chosen to use <emphasis>field access</emphasis> for
+ our entities, meaning the persistence implementation will
+ get and set persistent state directly through our class'
+ declared fields. We could have chosen to use <emphasis>
+ property access</emphasis>, in which the implementation
+ accesses persistent state through our JavaBean getter and
+ setter methods. In that case, we would have annotated our
+ getter methods rather than our fields.
+ </para>
+ <programlisting format="linespecific">
+@Id
+@GeneratedValue
+@Column(name="ID")
+private long id;
+
+@Basic @Column(name="ANIMAL_NAME")
+private String name = null;
+
+@Basic @Column(name="COST")
+private float price = 0f;
+</programlisting>
+ <para>
+ The annotations serve to map the fields into the database. For
+ more information on these and other annotations, see
+ <xref linkend="jpa_overview_meta"/>.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para><command>@Id</command>: This annotation indicates that
+ the field is to be mapped to a primary key column in
+ the database.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>@GeneratedValue</command>:
+ Indicates that the implementation will generate a
+ value for the field automatically.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>@Column</command>: This annotation describes
+ the column to which the field will be mapped. The
+ <command>name</command> attribute specifies the name
+ of the column.
+ </para>
+ </listitem>
+ <listitem>
+ <para><command>@Basic</command>: This annotation indicates
+ that the field is simply mapped into a column. There
+ are other annotations that indicate entity
+ relationships and other more complex mappings.
+ </para>
+ </listitem>
+ </orderedlist>
+ </listitem>
+ <listitem>
+ <para>Compile the <filename>.java</filename> files.</para>
+ <programlisting format="linespecific">
+javac *.java
+</programlisting>
+ <para>
+ You can use any java compiler instead of
+ <command>javac</command>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Enhance the persistent classes.</para>
+ <programlisting format="linespecific">
+openjpac -p persistence.xml Animal.java Dog.java
+</programlisting>
+ <para>
+ This step runs the OpenJPA enhancer on the
+ <filename>Animal.java</filename> and
+ <filename>Dog.java</filename> files mentioned above.
+ See <xref linkend="ref_guide_pc_enhance"/> of the Reference
+ Guide for more information on the enhancer, including how to
+ use automatic runtime enhancement.
+ </para>
+ <note>
+ <para>
+ The <literal>-p</literal> flag points the enhancer to your
+ <filename>persistence.xml</filename> configuration file.
+ All OpenJPA tools look for default configuration in a
+ resource called <filename>openjpa.xml</filename> or
+ <filename>META-INF/openjpa.xml</filename>. Thus you
+ can avoid passing the <literal>-p</literal> argument to
+ tools by using this configuration file name in place of
+ <filename>persistence.xml</filename>. See
+ <xref linkend="ref_guide_conf"/> in the Reference Guide
+ for details on OpenJPA configuration.
+ </para>
+ </note>
+ </listitem>
+ </orderedlist>
+ <section id="jpa_tutorial_chapter2_datastore">
+ <title>Configuring the Datastore</title>
+ <para>
+ Now that we've compiled the source files and enhanced the
+ persistent classes, we're ready to set up the database.
+ <ulink url="http://hsqldb.sourceforge.net">Hypersonic SQL</ulink>,
+ a pure Java relational database, is included in the OpenJPA
+ distribution.
+ We have included this database because it is simple to set up and
+ has a small memory footprint; however, you can use this tutorial
+ with any of the relational databases that we support. You can also
+ write your own plugin for any database that we do not support. For
+ the sake of simplicity, this tutorial only describes how to set up
+ connectivity to a Hypersonic SQL database. For more
+ information on how to connect to a different database or
+ how to add support for other databases, see
+ <xref linkend="ref_guide_dbsetup"/> of the
+ Reference Guide.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para><indexterm><primary>mappingtool</primary></indexterm>
+ Create the object-relational mappings and database schema.
+ </para>
+ <programlisting format="linespecific">
+mappingtool -p persistence.xml Animal.java Dog.java
+</programlisting>
+ <para>
+ This command propagates the necessary schema for the
+ specified classes to the database configured in
+ <filename>persistence.xml</filename>. If you are
+ using the default Hypersonic SQL setup, the first time you
+ run the mapping tool Hypersonic will create
+ <filename>tutorial_database.properties</filename> and
+ <filename>tutorial_database.script</filename> database
+ files in your current directory. To
+ delete the database, just delete these files.
+ </para>
+ <para>
+ By default, JPA uses object-relational mapping
+ information stored in annotations in your source files.
+ <xref linkend="jpa_overview_mapping"/> of the
+ JPA Overview will help you understand mapping
+ annotations.
+ Additionally, <xref linkend="ref_guide_mapping"/> of the
+ Reference Guide describes your other mapping options in
+ detail.
+ </para>
+ <para>
+ </para>
+ <para>
+ If you are curious, you can view the schema OpenJPA
+ created for the tutorial classes with OpenJPA's schema tool:
+ </para>
+ <programlisting format="linespecific">
+schematool -p persistence.xml -a reflect -f tmp.schema
+</programlisting>
+ <para>
+ This will create a <filename>tmp.schema</filename> file
+ with an XML representation of the database schema. The
+ XML should be self explanatory; see
+ <xref linkend="ref_guide_schema_xml"/>
+ of the Reference Guide for details. You may delete the
+ <filename>tmp.schema</filename> file before proceeding.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Populate the database with sample data.</para>
+ <programlisting format="linespecific">
+java tutorial.persistence.SeedDatabase
+</programlisting>
+ </listitem>
+ </orderedlist>
+ <para>
+ Congratulations! You have now created an JPA-accessible
+ persistent store, and seeded it with some sample data.
+ </para>
+ </section>
+ </section>
+ <section id="jpa_tutorial_chapter3">
+ <title>Inventory Maintenance</title>
+ <para>
+ The most important element of a successful pet store product, say the
+ experts, is an inventory maintenance mechanism. So, let's work on the
+ <classname>Animal</classname> and <classname>Dog</classname> classes a
+ bit to permit user interaction with the database.
+ </para>
+ <para>
+ This chapter should familiarize you with some of the basics of the
+ <ulink url="../../ejb-3_0-pr-spec-persistence.pdf">JPA
+ specification</ulink> and the mechanics of compiling and enhancing
+ persistent classes. You will also become familiar with the mapping
+ tool for propagating the persistent schema into the database.
+ </para>
+ <para>
+ First, let's add some code to
+ <filename>AnimalMaintenance.java</filename> that allows us to examine
+ the animals currently in the database.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Add code to <filename>AnimalMaintenance.java</filename>.
+ </para>
+ <para>
+ Modify the <methodname>getAnimals</methodname> method of
+ <filename>AnimalMaintenance.java</filename> to look like this:
+ </para>
+ <programlisting format="linespecific">
+ /**
+ * Return a list of animals that match the specified query filter.
+ *
+ * @param filter the JPQL filter to apply to the query
+ * @param cls the class of animal to query on
+ * @param em the EntityManager to obtain the query from
+ */
+ public static List getAnimals (String filter, EntityManager em)
+ {
+ // Execute a query for the specified filter.
+ Query query = em.createQuery (filter);
+ return query.getResultList ();
+ }
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Compile <filename>AnimalMaintenance.java</filename>.
+ </para>
+ <programlisting format="linespecific">
+javac AnimalMaintenance.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Take a look at the animals in the database.</para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance list Animal
+</programlisting>
+ <para>
+ Notice that <methodname>list</methodname> optionally takes a
+ query filter. Let's explore the database some more, this time
+ using filters:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance list "select a from Animal a where a.name = 'Binney'"
+java tutorial.persistence.AnimalMaintenance list "select a from Animal a where a.price <= 50"
+</programlisting>
+ <para>
+ The Java Persistence Query Language (JPQL) is designed to look
+ and behave much like an object oriented SQL dialect. The
+ <literal>name</literal> and <literal>price</literal> fields
+ identified in the above queries map to the member fields of
+ those names in <classname>
+ tutorial.persistence.Animal</classname>.
+ More details on JPQL syntax is available in
+ <xref linkend="jpa_overview_query"/> of the JPA Overview.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Great! Now that we can see the contents of the database,
+ let's add some code that lets us add and remove animals.
+ </para>
+ <section id="jpa_tutorial_chapter3_persist">
+ <title>Persisting Objects</title>
+ <para>
+ As new dogs are born or acquired, the store owner will
+ need to add new records to the inventory database. In this
+ section, we'll write the code to handle additions through
+ the <classname>tutorial.persistence.AnimalMaintenance</classname>
+ class.
+ </para>
+ <para>
+ This section will familiarize you with the mechanism for
+ storing persistent instances in a JPA entity
+ manager. We will create a new dog, obtain a
+ <classname>Transaction</classname> from a
+ <classname>EntityManager</classname>, and, within the
+ transaction, make the new dog object persistent.
+ </para>
+ <para><classname>tutorial.persistence.AnimalMaintenance</classname>
+ provides a reflection-based facility for creating any type of
+ animal, provided that the animal has a two-argument constructor
+ whose first argument corresponds to the name of the animal
+ and whose second argument is an implementation-specific
+ primitive. This reflection-based system is in place to keep this
+ tutorial short and remove repetitive creation mechanisms. It is
+ not a required part of the JPA specification.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>Add the following code to <filename>
+ AnimalMaintenance.java</filename>.
+ </para>
+ <para>
+ Modify the <methodname>persistObject</methodname> method of
+ <filename>AnimalMaintenance.java</filename> to look like
+ this:
+ </para>
+ <programlisting format="linespecific">
+ /**
+ * Performs the actual JPA work of putting <code>object</code>
+ * into the data store.
+ *
+ * @param object the object to persist in the data store
+ */
+ public static void persistObject (EntityManager em, Object object)
+ {
+ // Mark the beginning of the unit of work boundary.
+ em.getTransaction ().begin ();
+
+ em.persist (object);
+
+ // Mark the end of the unit of work boundary,
+ // and record all inserts in the database.
+ em.getTransaction ().commit ();
+ System.out.println ("Added " + object);
+ }
+</programlisting>
+ <note>
+ <para>In the above code, we pass in an
+ <classname>EntityManager</classname>.
+ <classname>EntityManager</classname>s may be either
+ container managed or application managed. In this tutorial,
+ because we're operating outside a container, we're using
+ application managed <classname>EntityManager</classname>s.
+ In managed environments,
+ <classname>EntityManager</classname>s are typically
+ container managed, and thus injected or looked up via JNDI.
+ Application managed <classname>EntityManager</classname>s
+ can be used in both managed and unmanaged environments, and
+ are created by an
+ <classname>EntityManagerFactory</classname>. An
+ <classname>EntityManagerFactory</classname> can be obtained
+ from the
+ <classname>javax.persistence.Persistence</classname> class.
+ This class provides some convenience methods for
+ obtaining an <classname>EntityManagerFactory</classname>.
+ </para>
+ </note>
+ </listitem>
+ <listitem>
+ <para>
+ Recompile <filename>AnimalMaintenance.java</filename>.
+ </para>
+ <programlisting format="linespecific">
+javac AnimalMaintenance.java
+</programlisting>
+ </listitem>
+ </orderedlist>
+ <para>
+ You now have a mechanism for adding new dogs to the database. Go
+ ahead and add some by running
+ <command>java tutorial.persistence.AnimalMaintenance add Dog <name> <price></command>
+ For example:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance add Dog Fluffy 35
+</programlisting>
+ <para>
+ You can view the contents of the database with:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance list Dog
+</programlisting>
+ </section>
+ <section id="jpa_tutorial_chapter3_delete">
+ <title>Deleting Objects</title>
+ <para>
+ What if someone decides to buy one of the dogs? The store owner
+ will need to remove that animal from the database, since it is no
+ longer in the inventory.
+ </para>
+ <para>
+ This section demonstrates how to remove data from the datastore.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Add the following code to <filename>AnimalMaintenance.java
+ </filename>.
+ </para>
+ <para>
+ Modify the <methodname>deleteObjects</methodname> method of
+ <filename>AnimalMaintenance.java</filename> to look like
+ this:
+ </para>
+ <programlisting format="linespecific">
+ /**
+ * Performs the actual JPA work of removing
+ * <code>objects</code> from the datastore.
+ *
+ * @param objects the objects to persist in the datastore
+ * @param em the EntityManager to delete with
+ */
+ public static void deleteObjects (Collection objects, EntityManager em)
+ {
+ // Mark the beginning of the unit of work boundary.
+ em.getTransaction ().begin ();
+
+ // This method removes the objects in 'objects' from the data store.
+ for (Object ob : objects)
+ {
+ System.out.println ("Removed animal: " + ob);
+ em.remove (ob);
+ }
+
+ // Mark the end of the unit of work boundary, and record all
+ // deletes in the database.
+ em.getTransaction ().commit ();
+ }
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Recompile <filename>AnimalMaintenance.java</filename>.
+ </para>
+ <programlisting format="linespecific">
+javac AnimalMaintenance.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Remove some animals from the database.</para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance remove <query>
+</programlisting>
+ <para>
+ Where <replaceable><query></replaceable> is a query
+ string like those used for listing animals above.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ All right. We now have a basic pet shop inventory
+ management system. From this base, we will add some of the
+ more advanced features suggested by our industry experts.
+ </para>
+ </section>
+ </section>
+ <section id="jpa_tutorial_chapter4">
+ <title>Inventory Growth</title>
+ <para>
+ Now that we have the basic pet store framework in place, let's add
+ support for the next pet in our list: the rabbit. The rabbit is a bit
+ different than the dog; pet stores sell them all for the same price,
+ but gender is critically important since rabbits reproduce rather
+ easily and quickly. Let's put together a class representing a rabbit.
+ </para>
+ <para>
+ In this chapter, you will see some more queries and write a
+ bidirectional relation between objects.
+ </para>
+ <para>
+ Provided with this tutorial is a file called
+ <filename>Rabbit.java</filename> which contains a sample
+ <classname>Rabbit</classname> implementation.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Examine <filename>Rabbit.java</filename>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The Rabbit class above contains a bidirectional
+ relationship between parents and children. From the Java side
+ of things, a bidirectional relationship is simply a
+ pair of fields that are conceptually linked. There is no
+ special Java work necessary to express bidirectionality.
+ However, you must identify the relationship as bidirectional
+ using JPA <link linkend="jpa_overview_meta">
+ annotations</link> so the mapping tool can create the most
+ efficient schema.
+ </para>
+ <para>
+ Insert this snippet of code immediately
+ <emphasis>before</emphasis> the <literal>children</literal>
+ field declaration in the <filename>Rabbit.java</filename> file.
+ </para>
+ <programlisting format="linespecific">
+ @ManyToMany
+ @JoinTable(name="RABBIT_CHILDREN",
+ joinColumns=@JoinColumn(name="PARENT_ID"),
+ inverseJoinColumns=@JoinColumn(name="CHILD_ID"))
+</programlisting>
+ <para>
+ The <literal>@ManyToMany</literal> annotation indicates that
+ <literal>children</literal> is one side of a many-to-many
+ relation. <literal>@JoinTable</literal> describes how this
+ relation maps to a database join table. The annotation's
+ <literal>joinColumns</literal> name the join table's foreign
+ key columns linking to the owning instance (the parent). In
+ this case, column <literal>RABBIT_CHILDREN.PARENT_ID</literal>
+ is a foreign key to the parent's <literal>ID</literal> primary
+ key column. Similarly, the <literal>inverseJoinColumns
+ </literal> attribute denotes the foreign key columns linking to
+ the collection elements (the children).
+ For more details on the <literal>@JoinTable</literal>
+ annotation, see <xref linkend="jpa_overview_mapping"/> of the
+ JPA Overview.
+ </para>
+ <para>
+ Now we'll map the other side of this bidirectional relation,
+ the <literal>parents</literal> field.
+ Insert the following snippet of code immediately
+ <emphasis>before</emphasis> the <command>parents</command>
+ field declaration in the <filename>Rabbit.java</filename> file.
+ The <literal>mappedBy</literal> attribute identifies the name
+ of the owning side of the relation.
+ </para>
+ <programlisting format="linespecific">
+ @ManyToMany(mappedBy="children")
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Compile <filename>Rabbit.java</filename>.
+ </para>
+ <programlisting format="linespecific">
+javac Rabbit.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Enhance the <classname>Rabbit</classname> class.
+ </para>
+ <programlisting format="linespecific">
+openjpac -p persistence.xml Rabbit.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Refresh the object-relational mappings and database schema.
+ </para>
+ <programlisting format="linespecific">
+mappingtool -p persistence.xml Rabbit.java
+</programlisting>
+ </listitem>
+ </orderedlist>
+ <para>
+ Now that we have a Rabbit class, let's get some preliminary rabbit
+ data into the database.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Add a <literal><class></literal> entry for <classname>
+ Rabbit</classname> to
+ <filename>../../META-INF/persistence.xml</filename>.
+ </para>
+ <programlisting format="linespecific">
+<class>tutorial.persistence.Rabbit</class>
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Create some rabbits.</para>
+ <para>
+ Run the following commands a few times to add some male
+ and female rabbits to the database:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance add Rabbit <name> false
+java tutorial.persistence.AnimalMaintenance add Rabbit <name> true
+</programlisting>
+ <para>
+ Now run some breeding iterations.
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.Rabbit breed 2
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Look at your new rabbits.</para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance list Rabbit
+java tutorial.persistence.AnimalMaintenance details "select r from Rabbit r where r.name = '<name>'"
+</programlisting>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section id="jpa_tutorial_chapter5">
+ <title>Behavioral Analysis</title>
+ <para>
+ Often, pet stores sell snakes as well as rabbits and dogs. Pet stores
+ are primarily concerned with a snake's length; much like rabbits, pet
+ store operators usually sell them all for a flat rate.
+ </para>
+ <para>
+ This chapter demonstrates more queries, schema manipulation,
+ and additional relation types.
+ </para>
+ <para>
+ Provided with this tutorial is a file called <filename>Snake.java
+ </filename> which contains a sample <classname>Snake</classname>
+ implementation. Let's get it compiled and loaded:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Examine and compile <filename>Snake.java</filename>.
+ </para>
+ <programlisting format="linespecific">
+javac Snake.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Enhance the class.</para>
+ <programlisting format="linespecific">
+openjpac -p persistence.xml Snake.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Refresh the mappings and database.</para>
+ <para>
+ As we have created a new persistent class, we must
+ map it to the database and change the schema to match. So
+ run the mapping tool:
+ </para>
+ <programlisting format="linespecific">
+mappingtool -p persistence.xml Snake.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Add a <literal><class></literal> entry for <classname>
+ Snake</classname> to
+ <filename>../../META-INF/persistence.xml</filename>.
+ </para>
+ <programlisting format="linespecific">
+<class>tutorial.persistence.Snake</class>
+</programlisting>
+ </listitem>
+ </orderedlist>
+ <para>
+ Once you have compiled everything, add a few snakes to the database
+ using:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance add Snake "name" <length>
+</programlisting>
+ <para>
+ Where <replaceable><length></replaceable> is the length in feet
+ for the new snake. To see the new snakes in the database, run:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance list Snake
+</programlisting>
+ <para>
+ Unfortunately for the massively developing rabbit population, snakes
+ often eat rabbits. Any good inventory system should be able to capture
+ this behavior. So, let's add some code to <filename>Snake.java
+ </filename> to support the snake's eating behavior.
+ </para>
+ <para>
+ First, let's modify <filename>Snake.java</filename> to contain a
+ list of eaten rabbits.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Add the following code snippets to
+ <filename>Snake.java</filename>.
+ </para>
+ <programlisting format="linespecific">
+ // This list will be persisted into the database as
+ // a one-to-many relation.
+ @OneToMany(mappedBy="eater")
+ private Set<Rabbit> giTract = new HashSet<Rabbit> ();
+</programlisting>
+ <para>
+ Note that we specified a <literal>mappedBy</literal>
+ attribute in this example. This is because the relation is
+ bidirectional; that is, the rabbit has knowledge of which
+ snake ate it. We could have left out the
+ <literal>eater</literal> field and instead created a
+ standard unidirectional relation. In fact, in a bidirectional
+ many-to-one relation, the many side must always be the owner.
+ </para>
+ <para>
+ For more information on types of relations, see
+ <xref linkend="jpa_overview_mapping_field"/> of the
+ JPA Overview.
+ </para>
+ <para>
+ Modify the <literal>toString (boolean)</literal> method to
+ output the giTract list.
+ </para>
+ <programlisting format="linespecific">
+ public String toString (boolean detailed)
+ {
+ StringBuffer buf = new StringBuffer (1024);
+ buf.append ("Snake ").append (getName ());
+
+ if (detailed)
+ {
+ buf.append (" (").append (length).append (" feet long) sells for ");
+ buf.append (getPrice ()).append (" dollars.");
+ buf.append (" Its gastrointestinal tract contains:\n");
+ for (Rabbit rabbit : giTract)
+ buf.append ("\t").append (rabbit).append ("\n");
+ }
+ else
+ buf.append ("; ate " + giTract.size () + " rabbits.");
+
+ return buf.toString ();
+ }
+</programlisting>
+ <para>
+ Add the following methods.
+ </para>
+ <programlisting format="linespecific">
+ /**
+ * Kills the specified rabbit and eats it.
+ */
+ public void eat (Rabbit dinner)
+ {
+ // Consume the rabbit.
+ dinner.kill ();
+ dinner.setEater (this);
+ giTract.add (dinner);
+ System.out.println ("Snake " + getName () + " ate rabbit "
+ + dinner.getName () + ".");
+ }
+
+
+ /**
+ * Locates the specified snake and tells it to eat a rabbit.
+ */
+ public static void eat (EntityManager em, String filter)
+ {
+ em.getTransaction ().begin ();
+
+ // Find the desired snake(s) in the data store.
+ Query query = em.createQuery (filter);
+ List<Snake> results = query.getResultList ();
+ if (results.isEmpty ())
+ {
+ System.out.println ("No snakes matching '" + filter + "' found");
+ return;
+ }
+
+ Query uneatenQuery = em.createQuery
+ ("select r from Rabbit r where r.isDead = false");
+ Random random = new Random ();
+ for (Snake snake : results)
+ {
+ // Run a query for a rabbit whose 'isDead' field indicates
+ // that it is alive.
+ List<Rabbit> menu = uneatenQuery.getResultList ();
+ if (menu.isEmpty ())
+ {
+ System.out.println ("No live rabbits in DB.");
+ break;
+ }
+
+ // Select a random rabbit from the list.
+ Rabbit dinner = menu.get (random.nextInt (menu.size ()));
+
+ // Perform the eating.
+ System.out.println (snake + " is eating:");
+ snake.eat (dinner);
+ }
+
+ em.getTransaction ().commit ();
+ }
+
+
+ public static void main (String[] args)
+ {
+ if (args.length == 2 && args[0].equals ("eat"))
+ {
+ EntityManagerFactory emf = Persistence.
+ createEntityManagerFactory (null);
+ EntityManager em = emf.createEntityManager ();
+ eat (em, args[1]);
+ em.close ();
+ emf.close ();
+ return;
+ }
+
+ // If we get here, something went wrong.
+ System.out.println ("Usage:");
+ System.out.println (" java tutorial.persistence.Snake eat "
+ + "\"snakequery\"");
+ }
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ Add an <literal>eater</literal> field to
+ <filename>Rabbit.java</filename>, and a getter and setter.
+ </para>
+ <programlisting format="linespecific">
+ @ManyToOne @JoinColumn(name="EATER_ID")
+ private Snake eater;
+
+ ...
+
+ public Snake getEater ()
+ {
+ return eater;
+ }
+
+
+ public void setEater (Snake snake)
+ {
+ eater = snake;
+ }
+</programlisting>
+ <para>
+ The <literal>@ManyToOne</literal> annotation indicates that this
+ is the many side of the bidirectional relation. The many side
+ must always be the owner in this type of relation. The
+ <literal>@JoinColumn</literal> describes the foreign key
+ that joins the rabbit table to the snake table. The rabbit
+ table has an <literal>EATER_ID</literal> column that is a
+ foreign key to the <literal>ID</literal> primary key column
+ of the snake table.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Compile <filename>Snake.java</filename> and
+ <filename>Rabbit.java</filename> and enhance the classes.
+ </para>
+ <programlisting format="linespecific">
+javac Snake.java Rabbit.java
+openjpac -p persistence.xml Snake.java Rabbit.java
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Refresh the mappings and database.</para>
+ <programlisting format="linespecific">
+mappingtool -p persistence.xml Snake.java Rabbit.java
+</programlisting>
+ </listitem>
+ </orderedlist>
+ <para>
+ Now, experiment with the following commands:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.Snake eat "select s from Snake s where s.name = '<name>'"
+java tutorial.persistence.AnimalMaintenance details "select s from Snake s where s.name = '<name>'"
+</programlisting>
+ <section id="jpa_tutorial_chapter5_query">
+ <title>Complex Queries</title>
+ <para>
+ Imagine that one of the snakes in the database was named Killer.
+ To find out which rabbits Killer ate, we could run either of the
+ following two queries:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance details "select s from Snake s where s.name = 'Killer'"
+java tutorial.persistence.AnimalMaintenance list "select r from Rabbit r where r.eater.name = 'Killer'"
+</programlisting>
+ <para>
+ The first query is snake-centric - the query runs against the
+ <classname>Snake</classname> class, looking for all snakes named
+ Killer and providing a detailed listing of them. The second is
+ rabbit-centric - it examines the rabbits in the database for
+ instances whose <literal>eater</literal> is named Killer.
+ This second query demonstrates the that simple java 'dot' syntax
+ is used when traversing an to-one field in a query.
+ </para>
+ <para>
+ It is also possible to traverse collection fields. Imagine that
+ there was a rabbit called Roger in the datastore and that one of
+ the snakes ate it. In order to determine who ate Roger Rabbit, you
+ could run a query like this:
+ </para>
+ <programlisting format="linespecific">
+java tutorial.persistence.AnimalMaintenance details "select s from Snake s inner join s.giTract r where r.name = 'Roger'"
+</programlisting>
+ </section>
+ </section>
+ <section id="jpa_tutorial-chapter6">
+ <title>Extra Features</title>
+ <para>
+ Congratulations! You are now the proud author of a pet store inventory
+ suite. Now that you have all the major features of the pet store
+ software implemented, it's time to add some extra features. You're on
+ your own; think of some features that you think a pet store should have,
+ or just explore the features of JPA.
+ </para>
+ <para>
+ Here are a couple of suggestions to get you started:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Animal pricing.</para>
+ <para>
+ Modify <classname>Animal</classname> to contain an inventory
+ cost and a resale price. Calculate the real dollar amount
+ eaten by the snakes (the sum of the inventory costs of all the
+ consumed rabbits), and the cost assuming that all the eaten
+ rabbits would have been sold had they been alive. Ignore the
+ fact that the rabbits, had they lived, would have created more
+ rabbits, and the implications of the reduced food costs due to
+ the not-quite-as-hungry snakes and the smaller number of
+ rabbits.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Dog categorization.</para>
+ <para>
+ Modify <classname>Dog</classname> to have a
+ relation to a new class called <classname>Breed</classname>,
+ which contains a name identifying the breed of the dog and a
+ description of the breed. Put together an admin tool for
+ breeds and for associating dogs and breeds.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+<!-- ### EJBDOC
+ &ejb3-reverse-tutorial.xml;
+ -->
+ <section id="jpa_j2ee_tutorial">
+ <title>J2EE Tutorial</title>
+ <para>
+ By deploying OpenJPA into a J2EE environment, you can maintain the
+ simplicity and performance of OpenJPA, while leveraging J2EE
+ technologies such as container managed transactions (JTA/JTS),
+ enterprise objects with remote invocation (EJB), and managed
+ deployment of multi-tiered applications via an application
+ server. This tutorial will demonstrate how to deploy OpenJPA-based
+ J2EE applications and showcase some basic enterprise JPA
+ design techniques. The tutorial's sample application models
+ a basic garage catalog system. While the application is
+ relatively trivial, the code has been constructed to illustrate
+ simple patterns and solutions to common problems when using
+ OpenJPA in an enterprise environment.
+ </para>
+ <section id="jpa_j2ee_tutorial_requirements">
+ <title>Prerequisites for the OpenJPA J2EE Tutorial</title>
+ <para>
+ This tutorial assumes that you have installed OpenJPA and
+ setup your classpath according to the installation instructions
+ appropriate for your platform. In addition, this
+ tutorial requires that you have installed and configured a
+ J2EE-compliant application server, such as WebLogic or JBoss,
+ running on JDK 1.5. If you use a different
+ application server not listed here, this tutorial may be adaptable to
+ your application server with small changes; refer to your application
+ server's documentation for any specific classpath and deployment
+ descriptor requirements.
+ </para>
+ <para>
+ This tutorial assumes a reasonable level of experience with
+ OpenJPA and JPA. We provide a number of other
+ tutorials for basic concepts, including enhancement, schema
+ mapping, and configuration. This tutorial also assumes a
+ basic level of experience with J2EE components, including
+ session beans, JNDI, JSP, and EAR/WAR/JAR packaging. Sun and/or
+ your application server company may provide tutorials to get
+ familiar with these components.
+ </para>
+ <para>
+ In addition, this tutorial uses Ant to build the deployment
+ archives. While this is the preferred way of building
+ a deployment of the tutorial, one can easily build the
+ appropriate JAR, WAR, and EAR files by hand, although that
+ is outside the scope of this document.
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_installation_types">
+ <title>J2EE Installation Types</title>
+ <para>
+ Every application server has a different installation process
+ for installing J2EE components. OpenJPA can be installed in a
+ number of ways, which may or may not be appropriate to your
+ application server. While this document focuses mainly upon
+ using OpenJPA as a JCA resource, there are other ways to use
+ OpenJPA in a J2EE environment.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>JPA</literal>: J2EE 5 allows for the
+ automatic injection of
+ <classname>EntityManager</classname> instances
+ into the J2EE context.
+ <!-- ### EJBDOC ###--></para>
+ </listitem>
+ <listitem>
+ <para><literal>JCA</literal>: OpenJPA implements the
+ JCA 1.0 spec, and the openjpa-persistence.rar file that comes in
+ the <filename>jca/persistence</filename> directory of the
+ distribution can be installed as any other JCA connection
+ resource. This is the preferred way to integrate OpenJPA into a
+ pre-J2EE 5 environment. It allows for simple installation
+ (usually involving uploading or copying openjpa-persistence.rar
+ into the application server's deployment directory), and
+ guided configuration on many appservers<!--
+ doesn't work yet , as well as dynamic reloading
+ for upgrading OpenJPA to a newer version-->.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Manual Binding into JNDI: Your application may require
+ some needs in initializing OpenJPA that go beyond the
+ JPA and JCA specifications. In this case, you can
+ manually instantiate OpenJPA and place it into the JNDI tree.
+ This process, however, is not seamless and can require a
+ fair bit of custom application server code to bind an
+ instance of
+ <classname>org.apache.openjpa.persistence.EntityManagerFactoryImpl</classname>
+ into JNDI.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="jpa_j2ee_tutorial_installing_sample">
+ <title>Installing the J2EE Sample Application</title>
+ <para>
+ Installing the sample application involves first compiling
+ and building a deployment archive (.ear) file. This file
+ then needs to be deployed into your application server.
+ </para>
+ <section id="jpa_j2ee_tutorial_building_sample">
+ <title>Compiling and Building The Sample Application</title>
+ <para>
+ Navigate to the <filename>samples/persistence/j2ee</filename>
+ directory of your OpenJPA installation.
+ </para>
+ <para>
+ Ensure that the JNDI name in the setSessionContext() method in
+ ejb/CarBean.java matches your JCA installation. This defaults to
+ <literal>java:/openjpa-ejb</literal>, but the actual value will depend
+ on the configuration of your JCA deploy and your application
+ server's JNDI context. E.g. the default name for a WebLogic 9
+ install would be simply <literal>openjpa-ejb</literal>.
+ </para>
+ <para>
+ Compile the source files in place both in this base directory
+ as well as the nested <filename>ejb</filename> and
+ <filename>jsp</filename> directories:
+ </para>
+ <programlisting format="linespecific">
+javac *.java ejb/*.java jsp/*.java
+</programlisting>
+ <para>
+ Enhance the Car class.
+ </para>
+ <programlisting format="linespecific">
+openjpac -p persistence.xml Car.java
+</programlisting>
+ <para>
+ Run the mapping tool; make sure that your <filename>
+ META-INF/persistence.xml</filename> file includes the same
+ connection information (e.g. Driver, URL, etc.) as your
+ JCA installation. You should update your JCA configuration
+ to include <classname>samples.persistence.j2ee.Car</classname>
+ in the <link linkend="openjpa.MetaDataFactory">MetaDataFactory</link>
+ property:
+ </para>
+ <programlisting format="linespecific">
+<config-property name="MetaDataFactory">Types=samples.persistence.j2ee.Car</config-property/>
+</programlisting>
+ <programlisting format="linespecific">
+mappingtool -p persistence.xml Car.java
+</programlisting>
+ <para>
+ Build an J2EE application archive by running Ant against the
+ <filename>build.xml</filename>. This will create
+ <filename>openjpa-persistence-j2ee-sample.ear</filename>. This ear
+ can now be deployed to your appserver. Be sure to add the class
+ <classname>samples.j2ee.Car</classname> to the
+ <literal>openjpa.PersistentClasses</literal> OpenJPA configuration
+ property. This will automatically register the Entity.
+ </para>
+ <programlisting format="linespecific">
+ant -f build.xml
+</programlisting>
+ </section>
+ <section id="jpa_j2ee_tutorial_sample_jboss">
+ <title>Deploying Sample To JBoss</title>
+ <para>
+ Place the ear file in the <filename>deploy</filename>
+ directory of your JBoss installation. You can use the
+ above hints to view the JNDI tree to see if
+ <classname>samples.j2ee.ejb.CarHome</classname> was
+ deployed to JNDI.
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_sample_weblogic">
+ <title>Deploying Sample To WebLogic 9</title>
+ <para>
+ Place the ear file in the <filename>autodeploy</filename>
+ directory of your WebLogic domain. Production mode (see your
+ startWebLogic.sh/cmd file) should be set to false to enable
+ auto-deployment. If the application was installed correctly,
+ you should see <computeroutput>openjpa-persistence-j2ee-sample
+ </computeroutput> listed in the Deployments section of the admin
+ console. In addition you should find <literal>CarHome</literal>
+ listed in the JNDI tree under
+ <computeroutput>AdminServer->samples->j2ee->ejb
+ </computeroutput>. Ensure that you have added the class
+ <classname>samples.j2ee.Car</classname> to the
+ <literal>openjpa.PersistentClasses</literal> OpenJPA configuration
+ property in the <literal>META-INF/ra.xml</literal> file.
+ </para>
+ </section>
+<!-- TODO
+ <section id="jpa_j2ee_tutorial_sample_weblogic8">
+ <title>Deploying Sample To WebLogic 8.1</title>
+ <para>
+ Create a new directory named <filename>
+ openjpa-persistence-j2ee-sample.ear</filename>
+ in the <filename>applications</filename> directory of
+ your WebLogic domain. Extract the EAR file (without copying
+ the EAR file) to this new directory:
+ </para>
+<programlisting>
+applications> mkdir openjpa-persistence-j2ee-sample.ear
+applications> cd openjpa-persistence-j2ee-sample.ear
+openjpa-persistence-j2ee-sample.ear> jar -xvf /path/to/openjpa-persistence-j2ee-sample.ear
+</programlisting>
+ <para>
+ Deploy the application by using the admin console
+ (Deployments -> Applications -> Deploy a new Application.
+ Select <literal>openjpa-persistence-j2ee-sample.ear</literal> and
+ deploy to the proper server targets. If you have installed the
+ application correctly, you should find CarHome
+ listed in the JNDI tree under
+ <computeroutput>myserver->samples->j2ee->ejb
+ </computeroutput>.
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_sample_sunone">
+ <title>Deploying Sample To SunONE / Sun JES</title>
+ <para>
+ Browse to the admin console in your web browser. Select
+ <computeroutput>Applications/ Enterprise Applications
+ </computeroutput> from the left navigation panel. Select
+ <computeroutput>Deploy... </computeroutput> and in the
+ following screen upload the <filename>
+ openjpa-persistence-j2ee-sample.ear</filename>
+ file to the server. Apply your changes by selecting the
+ link in the upper right portion of the page. You should
+ now see <computeroutput>openjpa-persistence-j2ee-sample
+ </computeroutput> listed
+ in the Enterprise Applications folder of the navigation panel.
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_sample_jrun">
+ <title>Deploying Sample To JRun</title>
+ <para>
+ Browse to the admin console in your web browser. Select
+ <computeroutput>J2EE Components
+ </computeroutput> from the left navigation panel. Select
+ <computeroutput>Add</computeroutput> under the
+ <computeroutput>Enterprise Applications</computeroutput>
+ heading. Select the <filename>openjpa-persistence-j2ee-sample.ear
+ </filename> file and hit <computeroutput>Deploy</computeroutput>.
+ You should now see <computeroutput>Sample-OpenJPAJ2EE</computeroutput>
+ listed in the top-level folder of the navigation panel.
+ Select it, and then select the
+ <computeroutput>sample-ejb.jar#CarEJB</computeroutput>
+ component under
+ <computeroutput>Enterprise JavaBeans</computeroutput>
+ section, then change the <computeroutput>JNDI Name</computeroutput>
+ for the bean from the default value to
+ <computeroutput>samples.j2ee.ejb.CarHome</computeroutput> and hit
+ <computeroutput>Apply</computeroutput>.
+ </para>
+ <para>
+ If the OpenJPA resource adapter and the sample EAR are both
+ configured correctly, you should now be able to access
+ your sample application at JRun's deploy URL (e.g.,
+ <literal>http://localhost:8100/sample/</literal>).
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_sample_websphere">
+ <title>Deploying Sample To WebSphere</title>
+ <para>
+ Browse to the admin console in your web browser. Select
+ <computeroutput>Applications / Install New Application
+ </computeroutput> from the left navigation panel. Select
+ the path to your <filename>openjpa-persistence-j2ee-sample.ear
+ </filename> file and press <computeroutput>Next</computeroutput>.
+ </para>
+ <para>
+ On the following screen, leave the options at the default
+ and select <computeroutput>Next</computeroutput>. On the following
+ screen (<computeroutput>Install New Application->Step 1
+ </computeroutput>), ensure that the <computeroutput>Deploy EJBs
+ </computeroutput> option is checked. Leave other options at their
+ defaults.
+ </para>
+ <para>
+ Move on to Step 2. On this screen enter <literal>
+ samples.j2ee.ejb.CarHome</literal> as the JNDI name for the
+ <classname>Car</classname> EJB. Continue through the
+ remaining steps leaving options at the defaults. Select
+ <computeroutput>Finish</computeroutput> and ensure that
+ the application is deployed correctly.
+ </para>
+ <para>
+ Save the changes to the domain configuration by either
+ selecting the <computeroutput>Save</computeroutput> link
+ that appears after the installation is complete or by
+ selecting <computeroutput>Save</computeroutput> from the top menu.
+ </para>
+ <para>
+ To verify your installation, select <computeroutput>Applications
+ / Enterprise Applications</computeroutput> from the left
+ navigation panel. <computeroutput>Sample-OpenJPAJ2EE</computeroutput>
+ should be listed in the list. If the application has not
+ started already, select the checkbox next to <computeroutput>
+ Sample-OpenJPAJ2EE</computeroutput>
+ and select <computeroutput>Start</computeroutput>.
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_sample_borland">
+ <title>Deploying Sample To Borland Enterprise Server 5.2</title>
+ <para>
+ Deploy the EAR file using iastool or the console. Note
+ that you may have to include the JDO library in your
+ stub generation process. Also be sure that you have
+ followed the JCA instructions for
+ BES as well as editing the ejb/CarBean.java file to
+ point to <literal>serial://openjpa-ejb</literal> JNDI location.
+ You should be able to see the CarEJB located in JNDI
+ located at the home classname.
+ </para>
+ </section>
+ -->
+ </section>
+ <section id="jpa_j2ee_tutorial_using">
+ <title>Using The Sample Application</title>
+ <para>
+ The sample application installs itself into the web layer at the
+ context root of sample. By browsing to
+ <computeroutput>http://yourserver:yourport/openjpa-persistence-j2ee-sample
+ </computeroutput>, you should be presented with a simple
+ list page with no cars. You can edit, add, delete car instances.
+ In addition, you can query on the underlying <classname>Car</classname>
+ instances by passing in an JPQL query into the marked form (such as
+ <computeroutput>select car from Car car where car.model="Some Model"</computeroutput>).
+ </para>
+ </section>
+ <section id="jpa_j2ee_tutorial_architecture">
+ <title>Sample Architecture</title>
+ <para>
+ The garage application is a simple enterprise application that
+ demonstrates some of the basic concepts necessary when
+ using OpenJPA in the enterprise layer.
+ </para>
+ <para>
+ The core model wraps a stateless session bean facade around
+ an entity. Using a session bean provides both a remote interface
+ for various clients as well as providing a transactional context in
+ which to work (and thus avoiding any explicit transactional code).
+ </para>
+ <para>
+ This session bean uses the JPA's detachment
+ capabilities to provide an automatic Data Transfer Object mechanism
+ for the primary communication between the
+ application server and the (possibly remote) client. The <classname>Car
+ </classname> instance will be used as the primary object upon
+ which the client will work.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>samples/persistence/j2ee/Car.java</literal>:
+ The core of the sample application. This is the
+ entity class that OpenJPA will use to persist the
+ application data.
+ Instances of this class will also fill the role of
+ data transfer object (DTO) for EJB clients.
+ To accomplish this, <classname>Car</classname> implements
+ <classname>java.io.Serializable</classname>
+ so that remote clients can access cars as parameters
+ and return values from the EJB.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>
+ samples/persistence/j2ee/jsp/SampleUtilities.java</literal>:
+ This is a simple facade to aggregate some common J2EE
+ behavior into some static methods.
+ By placing all of the functionality into a single
+ facade class, we can reduce code maintenance of our JSPs.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>samples/persistence/j2ee/ejb/Car*.java</literal>:
+ The source for the <classname>CarEJB</classname> session bean.
+ Clients can use the <classname>CarHome</classname>
+ and <classname>CarRemote</classname> interfaces to
+ find, manipulate, and persist changes to
+ <classname>Car</classname> transfer object
+ instances. By using J2EE transactional features,
+ the implementation code in <filename>CarBean.java</filename>
+ can be focused almost entirely upon business and
+ persistence logic without worrying about transactions.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>samples/persistence/j2ee/jsp/*.jsp</literal>:
+ The web presentation client. These JSPs are not aware of the
+ JPA; they simply use the <classname>CarEJB</classname> session
+ bean and the <classname>Car</classname> transfer object to do
+ all the work.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>samples/persistence/j2ee/resources/*</literal>:
+ Files required to deploy to the various appservers,
+ including J2EE deployment descriptors, WAR/ EJB/ EAR
+ descriptors, as well as appserver specific files.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>samples/persistence/j2ee/build.xml</literal>:
+ A simple Ant build file to help in creating a J2EE EAR file.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="jpa_j2ee_tutorial_notes">
+ <title>Code Notes and J2EE Tips</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ Entity classes are excellent
+ candidates for the Data Transfer Object Pattern.
+ This pattern attempts to reduce network load, as well
+ as group business logic into concise units.
+ For example, <methodname>CarBean.edit</methodname> allows you
+ to ensure that all values are correct before committing a
+ transaction, instead of sequentially calling getters and
+ setters on the session facade. This is especially true when
+ using RMI such as from a Swing based application
+ connecting to an application server.
+ </para>
+ <para><classname>CarEJB</classname> works as a session bean facade
+ to demarcate transactions, provide finder methods, and
+ encapsulate complex business logic at the server level.
+ </para>
+ </listitem>
+ <listitem>
+ <para><methodname>EntityManager.close()</methodname>
+ should be called at the end of every EJB method.
+ In addition to ensuring that your code will not attempt to
+ access a closed <classname>EntityManager</classname>, it
+ allows OpenJPA to free up unused resources.
+ Since an <classname>EntityManager</classname> is created
+ for every transaction, this can increase the scalability
+ of your application.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ You should not use <methodname>
+ EntityManager.getTransaction()</methodname> when using JTA
+ to manage your transactions. Instead, OpenJPA will integrate with
+ JTA to automatically govern transactions based on your EJB
+ transaction configuration.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ While serialization of entity instances is relatively
+ straightforward, there are several things to keep in mind:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ While "default fetch group" values will always be
+ returned to the client upon serialization, lazily
+ loaded fields will not as the
+ <classname>EntityManager</classname> will
+ have been closed before those fields attempt to
+ serialize. You can either access those fields
+ before serialization, configure the fetch type of the
+ relationships, or configure your JPQL queries to
+ eagerly fetch data.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>
+ It is not necessarily required that you use EJBs and
+ container-managed transactions to demarcate transactions,
+ although that is probably the most common method.
+ In EJBs using bean managed transactions, you can control
+ transactions through the
+ <classname>javax.transaction.UserTransaction</classname> interface.
+ Furthermore, outside of session beans you can control the
+ JPA layer's transaction via the
+ <classname>javax.persistence.EntityTransaction</classname>
+ interface.
+ </para>
+ </listitem>
+ <listitem>
+ <para><classname>EntityManager</classname>s are allocated on a
+ per-Transaction basis.
+ Calling <methodname>getEntityManager</methodname> from
+ the same <classname>EntityManagerFactory</classname>
+ within the same EJB method call will always return the same
+ entity manager, although the user-visible object may be
+ proxied, so might not compare equal using the
+ <literal>==</literal> operator.
+ </para>
+ </listitem>
+ </orderedlist>
+ </section>
+ </section>
+ </chapter>