OPENJPA-298

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@560342 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Patrick Linskey 2007-07-27 18:18:10 +00:00
parent 8586e0fef3
commit 58533057a0
6 changed files with 189 additions and 87 deletions

View File

@ -177,7 +177,7 @@ constructor.
<para>
OpenJPA's <emphasis>enhancer</emphasis> will automatically add a protected
no-arg constructor to your class when required. Therefore, this restriction does
not apply when using OpenJPA. See <xref linkend="ref_guide_pc_enhance"/>
not apply when using the enhancer. See <xref linkend="ref_guide_pc_enhance"/>
of the Reference Guide for details.
</para>
</note>

View File

@ -222,7 +222,7 @@ information.
<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:
and then optionally pass the resulting classes through the OpenJPA enhancer.
</para>
<note>
<para>
@ -387,7 +387,7 @@ You can use any java compiler instead of <command>javac</command>.
</listitem>
<listitem>
<para>
Enhance the persistent classes.
Enhance the persistent classes. (Optional)
</para>
<programlisting>
java org.apache.openjpa.enhance.PCEnhancer Animal.java Dog.java
@ -396,7 +396,7 @@ java org.apache.openjpa.enhance.PCEnhancer Animal.java Dog.java
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.
information on the enhancer, including alternatives to enhancement.
</para>
<note>
<para>
@ -417,7 +417,7 @@ OpenJPA configuration.
Configuring the Datastore
</title>
<para>
Now that we've compiled the source files and enhanced the persistent classes,
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
@ -819,7 +819,7 @@ javac Rabbit.java
</listitem>
<listitem>
<para>
Enhance the <classname>Rabbit</classname> class.
Enhance the <classname>Rabbit</classname> class. (Optional)
</para>
<programlisting>
java org.apache.openjpa.enhance.PCEnhancer Rabbit.java
@ -907,7 +907,7 @@ javac Snake.java
</listitem>
<listitem>
<para>
Enhance the class.
Enhance the class. (Optional)
</para>
<programlisting>
java org.apache.openjpa.enhance.PCEnhancer Snake.java
@ -1118,7 +1118,7 @@ key that joins the rabbit table to the snake table. The rabbit table has an
<listitem>
<para>
Compile <filename>Snake.java</filename> and <filename>Rabbit.java</filename> and
enhance the classes.
optionally enhance the classes.
</para>
<programlisting>
javac Snake.java Rabbit.java
@ -1320,7 +1320,7 @@ nested <filename>ejb</filename> and <filename>jsp</filename> directories:
javac *.java ejb/*.java jsp/*.java
</programlisting>
<para>
Enhance the Car class.
Enhance the Car class. (Optional)
</para>
<programlisting>
java org.apache.openjpa.enhance.PCEnhancer Car.java

View File

@ -7,15 +7,15 @@
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.
under the License.
-->
<chapter id="ref_guide_mapping">
<title>
@ -205,7 +205,7 @@ the action to take on each class. The available actions are:
<para>
<literal>buildSchema</literal>: This is the default action. It
makes the database schema match your existing mappings. If your provided
mappings conflict with your class definitions, OpenJPA will fail with an
mappings conflict with your class definitions, OpenJPA will fail with an
informative exception.
</para>
</listitem>
@ -548,7 +548,7 @@ generation.
<listitem>
<para>
<literal>-annotations/-ann &lt;true/t | false/f&gt;</literal>: Set to true to
generate JPA annotations in generated java classes.
generate JPA annotations in generated java classes.
</para>
</listitem>
<listitem>
@ -677,7 +677,7 @@ the system defaults to a
<classname>PropertiesReverseCustomizer</classname></ulink>. This customizer
allows you to specify simple customization options in the properties file given
with the <literal>-customizerProperties</literal> flag below. We present the
available property keys <link linkend="ref_guide_pc_reverse_custom">
available property keys <link linkend="ref_guide_pc_reverse_custom">
below</link>.
</para>
</listitem>
@ -714,12 +714,12 @@ generates.
<para>
After you are satisfied with the generated classes and their mappings, you
should first compile the classes with <literal>javac</literal>, <literal>
jikes</literal>, or your favorite Java compiler. Make sure the classes are
located in the directory corresponding to the <literal>-package</literal> flag
jikes</literal>, or your favorite Java compiler. Make sure the classes are
located in the directory corresponding to the <literal>-package</literal> flag
you gave the reverse mapping tool. Next, if you have generated an <filename>
orm.xml</filename>, move that file to a <filename>META-INF</filename> directory
within a directory in your classpath. Finally, enhance the classes
if necessary (see <xref linkend="ref_guide_pc_enhance"/> ).
if necessary (see <xref linkend="ref_guide_pc_enhance"/>).
</para>
</listitem>
</orderedlist>
@ -929,7 +929,7 @@ In the <emphasis>meet-in-the-middle</emphasis>
mapping approach, you control both the relational model and the object model. It
is up to you to define the mappings between these models. The mapping
tool's <literal>validate</literal> action is useful to meet-in-the-middle
mappers. This action verifies that the mapping information for a class matches
mappers. This action verifies that the mapping information for a class matches
the class definition and the existing schema. It throws an informative exception
when your mappings are incorrect.
</para>
@ -986,8 +986,8 @@ schema that matches your object model.
<para>
OpenJPA relies on foreign key constraint information at runtime to order SQL
appropriately. Be sure to set your mapping defaults to reflect your existing
database constraints, set the schema factory to reflect on the database for
constraint information (see <xref linkend="ref_guide_schema_info_factory"/>),
database constraints, set the schema factory to reflect on the database for
constraint information (see <xref linkend="ref_guide_schema_info_factory"/>),
or use explicit foreign key mappings as described in
<xref linkend="ref_guide_mapping_jpa_fk"/>.
</para>
@ -1015,7 +1015,7 @@ properties (though with different default values), as well as:
<listitem>
<para>
<literal>PrependFieldNameToJoinTableInverseJoinColumns</literal>: Whether to
prepend the owning field name to the names of inverse join columns in join
prepend the owning field name to the names of inverse join columns in join
tables. Defaults to true per the JPA specification. Set to false for
compatibility with older OpenJPA versions which did not prepend the field name.
</para>
@ -1281,8 +1281,8 @@ The bundled mapping factories are:
<para>
<literal>-</literal>: Leaving the <literal> openjpa.jdbc.MappingFactory
</literal> property unset allows your metadata factory to take over mappings as
well. If you are using the default <literal>jpa</literal> metadata factory,
OpenJPA will read mapping information from your annotations and
well. If you are using the default <literal>jpa</literal> metadata factory,
OpenJPA will read mapping information from your annotations and
<filename>orm.xml</filename> when you leave the mapping factory unspecified.
</para>
</listitem>
@ -2172,7 +2172,7 @@ public class Subscription {
</indexterm>
<para>
We detailed the <literal>ContainerTable</literal> annotation in
<xref linkend="ref_guide_mapping_jpa_coll_table"/>. Custom map mappings may
<xref linkend="ref_guide_mapping_jpa_coll_table"/>. Custom map mappings may
also use this annotation to represent a map table.
</para>
</section>
@ -2189,7 +2189,7 @@ batch size.
</para>
<para>
OpenJPA assumes certain columns have indexes or constraints based on your
mapping defaults, as detailed in <xref linkend="ref_guide_mapping_defaults"/>.
mapping defaults, as detailed in <xref linkend="ref_guide_mapping_defaults"/>.
You can override the configured defaults on individual joins, field
values, collection elements, map keys, or map values using the annotations
presented in the following sections.
@ -2267,7 +2267,7 @@ The <ulink url="../javadoc/org/apache/openjpa/persistence/jdbc/ForeignKey.html">
annotation represents a foreign key on the columns of a field. It is also used
within the <link linkend="ref_guide_mapping_jpa_coll_table"><classname>
ContainerTable</classname></link> annotation to set a database foreign key on
join columns. To set a constraint to the columns of a collection element, use
join columns. To set a constraint to the columns of a collection element, use
the
<ulink url="../javadoc/org/apache/openjpa/persistence/jdbc/ElementForeignKey.html">
<classname> org.apache.openjpa.persistence.jdbc.ElementForeignKey</classname>
@ -2397,20 +2397,20 @@ entity property mapped to an XML column.
<para>
Annotate the entity property using the XMLValueHandler strategy:
</para>
<programlisting>
<programlisting>
@Persistent
@Strategy(&quot;org.apache.openjpa.jdbc.meta.strats.XMLValueHandler&quot;)
</programlisting>
<para>
The default fetch type is EAGER but can be changed to LAZY by using:
</para>
<programlisting>
<programlisting>
@Persistence(fetch=FetchType.LAZY)
</programlisting>
<para>
The entity property class is required to have
jaxb binding annotations. This is produced when the classes are generated
from an xml schema using the jaxb generator XJC.Ensure that <classname>@XmlRootElement</classname>
jaxb binding annotations. This is produced when the classes are generated
from an xml schema using the jaxb generator XJC.Ensure that <classname>@XmlRootElement</classname>
appears in the root class. In some case this annotation needs to be added manually if it is missing.
</para>
<para>
@ -2427,8 +2427,8 @@ XML functions.
</para>
<para>
The path expression must be single valued.Path expressions over xml
mapped classes can only be used in WHERE as an operand to a simple predicate
(= &lt;&gt; &lt; &gt; &gt;= &lt;=).
mapped classes can only be used in WHERE as an operand to a simple predicate
(= &lt;&gt; &lt; &gt; &gt;= &lt;=).
</para>
<para>
Path expressions over XML mapped fields can not be:
@ -2456,9 +2456,9 @@ used in the FROM , GROUP BY, HAVING, ORDER BY clauses
</listitem>
</itemizedlist>
<para>
XML schema must not contain namespace declarations. The EJB query path
XML schema must not contain namespace declarations. The EJB query path
expressions can not refer to java fields generated from XML ANY type or
XML mixed element types.
XML mixed element types.
</para>
<para>
The datatype generated by JAXB must be a valid EJB query type
@ -2479,7 +2479,7 @@ in which the JPA entity Order has <classname>&lt;shipAddress&gt;</classname> per
&lt;xs:complexType name=&quot;Address&quot;&gt;
&lt;xs:sequence&gt;
&lt;xs:element name=&quot;Name&quot; type=&quot;xs:string&quot; /&gt;
&lt;xs:element name=&quot;Street&quot; type=&quot;xs:string&quot;
&lt;xs:element name=&quot;Street&quot; type=&quot;xs:string&quot;
minOccurs=&quot;1&quot; maxOccurs=&quot;3&quot; /&gt;
&lt;xs:element name=&quot;City&quot; type=&quot;xs:string&quot; /&gt;
&lt;/xs:sequence&gt;
@ -2524,8 +2524,8 @@ in which the JPA entity Order has <classname>&lt;shipAddress&gt;</classname> per
</example>
<para>
Java classes <link linkend="ref_guide_xmlmapping_address">Address</link>,
<link linkend="ref_guide_xmlmapping_usaaddress">USAAddress</link> and
<link linkend="ref_guide_xmlmapping_canaddress">CANAddress</link>
<link linkend="ref_guide_xmlmapping_usaaddress">USAAddress</link> and
<link linkend="ref_guide_xmlmapping_canaddress">CANAddress</link>
are produced using jaxb XJC generator from myaddress schema.
</para>
<example id="ref_guide_xmlmapping_address">
@ -2548,12 +2548,12 @@ public class Address {
protected List&lt;String&gt; street;
@XmlElement(name = &quot;City&quot;, required = true)
protected String city;
/**
* Getter and Setter methods.
*
*/
...
*
*/
...
}
</programlisting>
</example>
@ -2580,9 +2580,9 @@ public class USAAddress
/**
* Getter and Setter methods.
*
*/
...
*
*/
...
}
</programlisting>
</example>
@ -2609,10 +2609,10 @@ public class CANAddress
/**
* Getter and Setter methods.
*
*/
...
}
*
*/
...
}
</programlisting>
</example>
<example id="ref_guide_xmlmapping_annorder">
@ -2621,9 +2621,9 @@ public class CANAddress
</title>
<programlisting>
@Entity
public class Order {
public class Order {
@Id private into id;
@Persistent
@Persistent
@Strategy (&quot;org.apache.openjpa.jdbc.meta.strats.XMLValueHandler&quot;)
private Address shipAddress;
...
@ -2657,12 +2657,12 @@ em.persist(o1);
Sample EJB Queries for XML Column mapping
</title>
<programlisting>
. select o from Order o where o.shipAddress.city = &quot;San Jose&quot; or
. select o from Order o where o.shipAddress.city = &quot;San Jose&quot; or
o.shipAddress.city = &quot;San Francisco&quot; (OK)
. select o.shipaAddress from Order o (OK)
. select o.shipAddress.city from Order o (INVALID)
. select o.shipaAddress from Order o (OK)
. select o.shipAddress.city from Order o (INVALID)
. select o from Order o where o.shipAddress.street = &quot;San Jose&quot; (INVALID multi valued)
</programlisting>
@ -3044,7 +3044,7 @@ array or collection element relations, respectively:
</seealso>
</indexterm>
<para>
OpenJPA's
OpenJPA's
<ulink url="../javadoc/org/apache/openjpa/persistence/jdbc/Strategy.html">
<classname>org.apache.openjpa.persistence.jdbc.Strategy</classname></ulink>
extension allows you to specify a custom mapping
@ -3174,8 +3174,8 @@ or more simple values. All value handlers implement the <classname>
org.apache.openjpa.jdbc.meta.ValueHandler</classname> interface; see its
<ulink url="../javadoc/org/apache/openjpa/jdbc/meta/ValueHandler.html"> Javadoc
</ulink> for details. Also, examine the built-in handlers in the <filename>
src/openjpa/jdbc/meta/strats</filename> directory of your OpenJPA source
distribution. Use these functional implementations as examples when you
src/openjpa/jdbc/meta/strats</filename> directory of your OpenJPA source
distribution. Use these functional implementations as examples when you
create your own value handlers.
</para>
</section>
@ -3227,7 +3227,7 @@ MappingDefaults</classname> implementations allows you to globally associate
field types with their corresponding custom value handler or strategy. OpenJPA
will automatically use your custom strategies when it encounters a field of the
associated type. OpenJPA will use your custom value handlers whenever it
encounters a field of the associated type.
encounters a field of the associated type.
<xref linkend="ref_guide_mapping_defaults"/> described mapping
defaults in detail.
</para>

View File

@ -167,6 +167,25 @@ OpenJPAEntityManager.setPopulateDataCache</ulink>
</para>
</entry>
</row>
<row>
<entry colname="name">
<emphasis role="bold">
Run the OpenJPA enhancer on your persistent classes,
either at build-time or deploy-time.
</emphasis>
<para>
<emphasis>performance, scalability, memory footprint</emphasis>
</para>
</entry>
<entry colname="desc">
OpenJPA performs best when your persistent classes have been run through the
OpenJPA post-compilation bytecode enhancer. When dealing with enhanced classes,
OpenJPA can make a number of assumptions that reduce memory footprint and
accelerate persistent data access. When evaluating OpenJPA's performance,
build-time or deploy-time enhancement should be enabled. See
<xref linkend="ref_guide_pc_enhance"/> for details.
</entry>
</row>
<row>
<entry colname="name">
<emphasis role="bold">

View File

@ -114,7 +114,7 @@ any unlisted class is not persistent.
</indexterm>
<para>
In order to provide optimal runtime performance, flexible lazy loading, and
efficient, immediate dirty tracking, OpenJPA uses an <emphasis> enhancer
efficient, immediate dirty tracking, OpenJPA can use an <emphasis>enhancer
</emphasis>. An enhancer is a tool that automatically adds code to your
persistent classes after you have written them. The enhancer post-processes the
bytecode generated by your Java compiler, adding the necessary fields and
@ -139,7 +139,7 @@ the <methodname>getId</methodname> method in your source file.
The diagram above illustrates the compilation of a persistent class.
</para>
<para>
You can add the OpenJPA enhancer to your build process, or use Java 1.5's new
You can add the OpenJPA enhancer to your build process, or use Java 1.5's
instrumentation features to transparently enhance persistent classes when they
are loaded into the JVM. The following sections describe each option.
</para>
@ -269,14 +269,14 @@ class load error, simply re-compile and re-enhance the offending classes.
</tertiary>
</indexterm>
<para>
The JEE 5 specification includes hooks to automatically enhance JPA entities
when they are deployed into a container. Thus, if you are using a JEE
The Java EE 5 specification includes hooks to automatically enhance JPA entities
when they are deployed into a container. Thus, if you are using a Java EE
5-compliant application server, OpenJPA will enhance your entities automatically
at runtime. Note that if you prefer build-time enhancement, OpenJPA's runtime
enhancer will correctly recognize and skip pre-enhanced classes.
</para>
<para>
If your application server does not support the JEE 5 enhancement hooks,
If your application server does not support the Java EE 5 enhancement hooks,
consider using the build-time enhancement described above, or the more general
runtime enhancement described in the next section.
</para>
@ -325,7 +325,7 @@ java -javaagent:/home/dev/openjpa/lib/openjpa.jar com.xyz.Main
<para>
You can pass settings to the agent using OpenJPA's plugin syntax (see
<xref linkend="ref_guide_conf_plugins"/>). The agent accepts the long
form of any of the standard configuration options
form of any of the standard configuration options
(<xref linkend="ref_guide_conf_devtools"/> ). It also accepts the following
options, the first three of which correspond exactly to to the same-named
options of the enhancer tool described in
@ -351,6 +351,20 @@ check whether each class loaded into the JVM is persistent, and enhance it
accordingly. This may slow down class load times significantly.
</para>
</listitem>
<listitem>
<para>
<literal>runtimeEnhancement</literal>: Boolean controlling whether OpenJPA
class enhancement should be available in this JVM execution. Default:
<literal>true</literal>
</para>
</listitem>
<listitem>
<para>
<literal>runtimeRedefinition</literal>: Boolean controlling whether OpenJPA
class redefinition should be available in this JVM execution. Default:
<literal>true</literal>
</para>
</listitem>
</itemizedlist>
<example id="ref_guide_pc_enhance_runtime_opt_ex">
<title>
@ -361,38 +375,107 @@ java -javaagent:/home/dev/openjpa/lib/openjpa.jar=addDefaultConstructor=false co
</programlisting>
</example>
</section>
<section id="ref_guide_pc_enhance_sercompat">
<section id="ref_guide_pc_enhance_unenhanced_types">
<title>
Serializing Enhanced Types
Omitting the OpenJPA enhancer
</title>
<indexterm zone="ref_guide_pc_enhance_sercompat">
<indexterm zone="ref_guide_pc_enhance_unenhanced_types">
<primary>
enhancer
</primary>
<secondary>
serialization
omitting
</secondary>
<tertiary>
of enhanced types
outside a container
</tertiary>
</indexterm>
<indexterm zone="ref_guide_pc_enhance_sercompat">
<primary>
serialization
</primary>
<secondary>
of enhanced types
</secondary>
</indexterm>
<para>
By default, OpenJPA maintains serialization compatibility between the enhanced
and unenhanced versions of a class. This allows you to serialize instances
between a server using OpenJPA and a client that does not have access to
enhanced classes or OpenJPA libraries. In some cases, however, you can make the
persist and attach processes more robust and efficient by allowing breaks in
serialization compatibility. See <xref linkend="ref_guide_detach_graph"/>
for details.
</para>
OpenJPA does not require that the enhancer be run. If you do not run the
enhancer, OpenJPA will fall back to one of several possible alternatives for
state tracking, depending on the execution environment.
</para>
<itemizedlist>
<listitem><para>
<emphasis>Deploy-time enhancement</emphasis>: if you are running your
application inside a Java EE 5 container, or another environment that supports
the JPA container contract, then OpenJPA will automatically perform class
transformation at deploy time.
</para></listitem>
<listitem><para>
<emphasis>Java 6 class retransformation</emphasis>: if you are running your
application in a Java 6 environment, OpenJPA will attempt to dynamically
register a <literal>ClassTransformer</literal> that will redefine your
persistent classes on the fly to track access to persistent data. Additionally,
OpenJPA will create a subclass for each of your persistent classes. When
you execute a query or traverse a relation, OpenJPA will return an instance
of the subclass. This means that the <literal>instanceof</literal> operator
will work as expected, but <literal>o.getClass()</literal> will return the
subclass instead of the class that you wrote.
</para>
<para>
You do not need to do anything at all to get this behavior. OpenJPA will
automatically detect whether or not the execution environment is capable of
Java 6 class retransformation.
</para></listitem>
<listitem><para>
<emphasis>Java 5 class redefinition</emphasis>: if you are running your
application in a Java 5 environment, and you specify the OpenJPA javaagent,
OpenJPA will use Java 5 class redefinition to redefine any persistent classes
that are not enhanced by thet OpenJPA javaagent. Aside from the requirement
that you specify a javaagent on the command line, this behavior is exactly the
same as the Java 6 class retransformation behavior. Of course, since the
OpenJPA javaagent performs enhancement by default, this will only be available
if you set the <literal>runtimeEnhancement</literal> javaagent flag to
<literal>false</literal>, or on any classes that are skipped by the OpenJPA
runtime enhancement process for some reason.
</para></listitem>
<listitem><para>
<emphasis>state comparison and subclassing</emphasis>: if you are running
in a Java 5 environment without a javaagent, or in a Java 6 environment that
does not support class retransformation, OpenJPA will still create subclasses
as outlined above. However, in some cases, OpenJPA may not be able to receive
notifications when you read or write persistent data.
</para>
<para>
If you are using <emphasis>property access</emphasis> for your persistent data,
then OpenJPA will be able to track all accesses for instances that you load
from the database, but not for instances that you create. This is because
OpenJPA will create new instances of its dynamically-generated subclass when
it loads data from the database. The dynamically-generated subclass has
code in the setters and getters that notify OpenJPA about persistent data
access. This means that new instances that you create will be subject to
state-comparison checks (see discussion below) to compute which fields to
write to the database, and that OpenJPA will ignore requests to evict
persistent data from such instances. In practice, this is not a particularly
bad limitation, since OpenJPA already knows that it must insert all field
values for new instances. So, this is only really an issue if you flush
changes to the database while inserting new records; after such a flush,
OpenJPA will need to hold potentially-unneeded hard references to the
new-flushed instances.
</para>
<para>
If you are using <emphasis>field access</emphasis> for your persistent data,
then OpenJPA will not be able to track accesses for any instances, including
ones that you load from the database. So, OpenJPA will perform state-comparison
checks to determine which fields are dirty. These state comparison checks are
costly in two ways. First, there is a performance penalty at flush / commit
time, since OpenJPA must walk through every field of every instance to determine
which fields of which records are dirty. Second, there is a memory penalty,
since OpenJPA must hold hard references to all instances that were loaded at
any time in a given transaction, and since OpenJPA must keep a copy of all
the initial values of the loaded data for later comparison. Additionally,
OpenJPA will ignore requests to evict persistent state for these types of
instances. Finally, the default lazy loading configuration will be ignored for
single-valued fields (one-to-one, many-to-one, and any other non-collection
or non-map field that has a lazy loading configuration). If you use fetch
groups or programmatically configure your fetch plan, OpenJPA will obey these
directives, but will be unable to lazily load any data that you exclude from
loading. As a result of these limitations, it is not recommended that you use
field access if you are not either running the enhancer or using OpenJPA with
a javaagent or in a Java 6 environment.
</para></listitem>
</itemizedlist>
</section>
</section>
<section id="ref_guide_pc_oid">

View File

@ -102,7 +102,7 @@ Compile the classes:
<listitem>
<para>
You should then proceed to pass in the configuration file you are using to the
enhancer:
enhancer: (Optional)
</para>
<para>
<userinput>java org.apache.openjpa.enhance.PCEnhancer -p persistence.xml Machine.java Crane.java Bulldozer.java