| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| <chapter id="jpa_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> 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> |
| <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> |
| org.apache.openjpa.enhance.PCEnhancer |
| </primary> |
| </indexterm> |
| <command>org.apache.openjpa.enhance.PCEnhancer</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> |
| org.apache.openjpa.jdbc.meta.MappingTool |
| </primary> |
| </indexterm> |
| <command>org.apache.openjpa.jdbc.meta.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 optionally 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> |
| @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> |
| @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> |
| javac *.java |
| </programlisting> |
| <para> |
| You can use any Java compiler instead of <command>javac</command>. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Enhance the persistent classes. (Optional) |
| </para> |
| <programlisting> |
| java org.apache.openjpa.enhance.PCEnhancer 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 alternatives to 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, |
| 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> |
| org.apache.openjpa.jdbc.meta.MappingTool |
| </primary> |
| </indexterm> |
| Create the object-relational mappings and database schema. |
| </para> |
| <programlisting> |
| java org.apache.openjpa.jdbc.meta.MappingTool 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> |
| java org.apache.openjpa.jdbc.schema.SchemaTool -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> |
| 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> |
| /** |
| * 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> |
| javac AnimalMaintenance.java |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Take a look at the animals in the database. |
| </para> |
| <programlisting> |
| 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> |
| 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> |
| /** |
| * 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> |
| 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> |
| java tutorial.persistence.AnimalMaintenance add Dog Fluffy 35 |
| </programlisting> |
| <para> |
| You can view the contents of the database with: |
| </para> |
| <programlisting> |
| 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> |
| /** |
| * 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> |
| javac AnimalMaintenance.java |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Remove some animals from the database. |
| </para> |
| <programlisting> |
| 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> |
| @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> |
| @ManyToMany(mappedBy="children") |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Compile <filename>Rabbit.java</filename>. |
| </para> |
| <programlisting> |
| javac Rabbit.java |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Enhance the <classname>Rabbit</classname> class. (Optional) |
| </para> |
| <programlisting> |
| java org.apache.openjpa.enhance.PCEnhancer Rabbit.java |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Refresh the object-relational mappings and database schema. |
| </para> |
| <programlisting> |
| java org.apache.openjpa.jdbc.meta.MappingTool 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> |
| <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> |
| 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> |
| java tutorial.persistence.Rabbit breed 2 |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Look at your new rabbits. |
| </para> |
| <programlisting> |
| 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> |
| javac Snake.java |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Enhance the class. (Optional) |
| </para> |
| <programlisting> |
| java org.apache.openjpa.enhance.PCEnhancer 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> |
| java org.apache.openjpa.jdbc.meta.MappingTool 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> |
| <class>tutorial.persistence.Snake</class> |
| </programlisting> |
| </listitem> |
| </orderedlist> |
| <para> |
| Once you have compiled everything, add a few snakes to the database using: |
| </para> |
| <programlisting> |
| 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> |
| 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> |
| // 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> |
| 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> |
| /** |
| * 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> |
| @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 |
| optionally enhance the classes. |
| </para> |
| <programlisting> |
| javac Snake.java Rabbit.java |
| java org.apache.openjpa.enhance.PCEnhancer Snake.java Rabbit.java |
| </programlisting> |
| </listitem> |
| <listitem> |
| <para> |
| Refresh the mappings and database. |
| </para> |
| <programlisting> |
| java org.apache.openjpa.jdbc.meta.MappingTool Snake.java Rabbit.java |
| </programlisting> |
| </listitem> |
| </orderedlist> |
| <para> |
| Now, experiment with the following commands: |
| </para> |
| <programlisting> |
| 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> |
| 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 that the simple Java 'dot' syntax is used when |
| traversing a 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> |
| 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> |
| <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. |
| </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> |
| javac *.java ejb/*.java jsp/*.java |
| </programlisting> |
| <para> |
| Enhance the Car class. (Optional) |
| </para> |
| <programlisting> |
| java org.apache.openjpa.enhance.PCEnhancer 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> |
| <config-property name="MetaDataFactory">Types=samples.persistence.j2ee.Car</config-property/> |
| </programlisting> |
| <programlisting> |
| java org.apache.openjpa.jdbc.meta.MappingTool 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> |
| 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> |
| </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> |