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 [13/18] - in /incubator/openjpa/trunk/openjpa-project:
./ src/doc/manual/
Added: incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_mapping.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_mapping.xml?rev=433761&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_mapping.xml (added)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_mapping.xml Tue Aug 22 14:28:53 2006
@@ -0,0 +1,3162 @@
+
+ <chapter id="ref_guide_mapping">
+ <title>Mapping</title>
+ <indexterm zone="ref_guide_mapping">
+ <primary>mapping metadata</primary>
+ </indexterm>
+ <para>
+ The JPA Overview's <xref linkend="jpa_overview_mapping"/>
+ explains object-relational mapping under JPA. This chapter reviews the
+ mapping utilities OpenJPA provides and examines OpenJPA features that go beyond
+ the JPA specification.
+ </para>
+ <section id="ref_guide_mapping_mappingtool">
+ <title>Forward Mapping</title>
+ <indexterm zone="ref_guide_mapping_mappingtool">
+ <primary>forward mapping</primary>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_mappingtool">
+ <primary>mapping tool</primary>
+ <seealso>forward mapping</seealso>
+ </indexterm>
+ <indexterm>
+ <primary>mapping metadata</primary>
+ <secondary>forward mapping</secondary>
+ <see>forward mapping</see>
+ </indexterm>
+ <para><emphasis>Forward mapping</emphasis> is the process of creating
+ mappings and their corresponding database schema from your object
+ model. OpenJPA supports forward mapping through the <emphasis>mapping
+ tool</emphasis>. The next section presents several common mapping tool
+ use cases. You can invoke the tool through the <literal>mappingtool
+ </literal> shell/batch script included in the OpenJPA distribution,
+ or through its Java class,
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/MappingTool"><classname>
+ org.apache.openjpa.jdbc.meta.MappingTool</classname></ulink>.
+ </para>
+ <note>
+ <para><xref linkend="ref_guide_integration_mappingtool"/>
+ describes the mapping tool Ant task.
+ </para>
+ </note>
+ <example id="ref_guide_mapping_mappingtool_typical">
+ <title>Using the Mapping Tool</title>
+ <programlisting format="linespecific">
+mappingtool Magazine.java
+</programlisting>
+ </example>
+ <para>
+ In addition to the universal flags of the
+ <link linkend="ref_guide_conf_devtools">configuration framework</link>,
+ the mapping tool accepts the following command line arguments:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>-schemaAction/-sa <add | refresh | drop | build
+ | retain | none></literal>: The action to take on the
+ schema. These options correspond to the same-named actions on
+ the schema tool described in
+ <xref linkend="ref_guide_schema_schematool"/>.
+ Unless you are running the mapping tool on all of your
+ persistent types at once or dropping a mapping, we strongly
+ recommend you use the default <literal>add</literal> action or
+ the <literal>build</literal> action. Otherwise you may end up
+ inadvertently dropping schema components that are used by
+ classes you are not currently running the tool over.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-schemaFile/-sf <stdout | output file></literal>:
+ Use this option to write the planned schema to an XML
+ document rather than modify the database. The document can
+ then be manipulated and committed to the database with the
+ <link linkend="ref_guide_schema_schematool">
+ schema tool</link>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-sqlFile/-sql <stdout | output file></literal>:
+ Use this option to write the planned schema modifications to
+ a SQL script rather than modify the database. Combine this
+ with a <literal>schemaAction</literal> of
+ <literal>build</literal> to generate a script that recreates
+ the schema for the current mappings, even if the schema already
+ exists.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-dropTables/-dt <true/t | false/f></literal>:
+ Corresponds to the same-named option on the schema tool.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-dropSequences/-dsq <true/t | false/f></literal>:
+ Corresponds to the same-named option on the schema tool.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-openjpaTables/-kt <true/t | false/f></literal>:
+ Corresponds to the same-named option on the schema tool.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-ignoreErrors/-i <true/t | false/f></literal>:
+ Corresponds to the same-named option on the schema tool.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-schemas/-s <schema and table names></literal>:
+ Corresponds to the same-named option on the schema tool.
+ This option is ignored if <literal>readSchema</literal> is not
+ set to <literal>true</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-readSchema/-rs <true/t | false/f></literal>:
+ Set this option to <literal>true</literal> to read the entire
+ existing schema when the tool runs. Reading the existing schema
+ ensures that OpenJPA does not generate any mappings that use
+ table, index, primary key, or foreign key names that conflict
+ with existing names. Depending on the JDBC driver, though,
+ it can be a slow process for large schemas.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-primaryKeys/-pk <true/t | false/f></literal>:
+ Whether to read and manipulate primary key information of
+ existing tables. Defaults to false.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-foreignKeys/-fk <true/t | false/f></literal>:
+ Whether to read and manipulate foreign key information of
+ existing tables. Defaults to false. This means that to add
+ any new foreign keys to a class that has already been mapped,
+ you must explicitly set this flag to true.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-indexes/-ix <true/t | false/f></literal>:
+ Whether to read and manipulate index information of
+ existing tables. Defaults to false. This means that to add
+ any new indexes to a class that has already been mapped once,
+ you must explicitly set this flag to true.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-sequences/-sq <true/t | false/f></literal>:
+ Whether to manipulate sequences. Defaults to true.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-meta/-m <true/t | false/f></literal>: Whether
+ the given action applies to metadata rather than or in addition
+ to mappings.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The mapping tool also uses an <literal>-action/-a</literal> argument
+ to specify the action to take on each class. The available actions are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>buildSchema</literal>: This is the default action when
+ using JPA mapping defaults (see
+ <xref linkend="ref_guide_mapping_defaults"/>). It makes the
+ database schema match your existing mappings. If your provided
+ mappings conflict with a class definition, OpenJPA will fail with
+ an informative exception.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>validate</literal>: Ensure that the mappings for
+ the given classes are valid and that they match the schema.
+ No mappings or tables will be changed. An exception is
+ thrown if any mappings are invalid.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Each additional argument to the tool should be one of:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>The full name of a persistent class.</para>
+ </listitem>
+ <listitem>
+ <para>The .java file for a persistent class.</para>
+ </listitem>
+ <listitem>
+ <para>
+ The <filename>.class</filename> file of a persistent class.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ If you do not supply any arguments to the mapping tool, it will run on
+ the classes in your persistent classes list (see
+ <xref linkend="ref_guide_pc_pcclasses"/>).
+ </para>
+ <para>
+ The mappings generated by the mapping tool are stored by the system
+ <emphasis>mapping factory</emphasis>.
+ <xref linkend="ref_guide_mapping_factory"/> discusses your mapping
+ factory options.
+ </para>
+ <section id="ref_guide_mapping_mappingtool_examples">
+ <title>Using the Mapping Tool</title>
+ <indexterm zone="ref_guide_mapping_mappingtool_examples">
+ <primary>mapping tool</primary>
+ <secondary>use cases</secondary>
+ </indexterm>
+ <para>
+ The JPA specification defines a comprehensive set of
+ defaults for missing mapping information. Thus, forward mapping
+ in JPA is virtually automatic. After using the mapping
+ annotations covered in <xref linkend="jpa_overview_mapping"/> of
+ the JPA Overview to override any unsatisfactory
+ defaults, run the mapping tool's <literal>buildSchema</literal>
+ action on your persistent classes. This is the default action when
+ you use JPA mapping defaults
+ (see <xref linkend="ref_guide_mapping_defaults"/>).
+ </para>
+ <para>
+ The <literal>buildSchema</literal> action manipulates the database
+ schema to match your mappings. It fails if any of your mappings
+ don't match your object model.
+ </para>
+ <example id="ref_guide_mapping_mappingtool_buildschema">
+ <title>Creating the Relational Schema from Mappings</title>
+ <programlisting format="linespecific">
+mappingtool Magazine.java
+</programlisting>
+ </example>
+ <para>
+ To drop the schema for a persistent class, set the mapping tool's
+ <literal>schemaAction</literal> to <literal>drop</literal>.
+ </para>
+ <example id="ref_guide_mapping_mappingtool_dropschema">
+ <title>Dropping Mappings and Association Schema</title>
+ <programlisting format="linespecific">
+mappingtool -sa drop Magazine.java
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_ddl_examples">
+ <title>Generating DDL SQL</title>
+ <indexterm zone="ref_guide_ddl_examples">
+ <primary>mapping tool</primary>
+ <secondary>DDL generation</secondary>
+ </indexterm>
+ <indexterm zone="ref_guide_ddl_examples">
+ <primary>DDL</primary>
+ <secondary>with mapping tool</secondary>
+ </indexterm>
+ <para>
+ The examples below show how to use the mapping tool to generate
+ DDL SQL scripts, rather than modifying the database directly.
+ </para>
+ <example id="ref_guid_mapping_ddl_full_ddl">
+ <title>Create DDL for Current Mappings</title>
+ <para>
+ This example uses your existing mappings to determine the
+ needed schema, then writes the SQL to create that schema to
+ <filename>create.sql</filename>.
+ </para>
+ <programlisting format="linespecific">
+mappingtool -a buildSchema -sa build -sql create.sql Magazine.java
+</programlisting>
+ </example>
+ <example id="ref_guid_mapping_ddl_part_ddl">
+ <title>Create DDL to Update Database for Current
+ Mappings</title>
+ <para>
+ This example uses your existing mappings to determine the
+ needed schema. It then writes the SQL to add any missing
+ tables and columns to the current schema to
+ <filename>update.sql</filename>.
+ </para>
+ <programlisting format="linespecific">
+mappingtool -a buildSchema -sql update.sql Magazine.java
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_mapping_synch">
+ <title>Runtime Forward Mapping</title>
+ <indexterm zone="ref_guide_mapping_synch">
+ <primary>forward mapping</primary>
+ <secondary>automatic runtime mapping</secondary>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_synch">
+ <primary>mapping metadata</primary>
+ <secondary>automatic runtime mapping</secondary>
+ </indexterm>
+ <para>
+ You can configure OpenJPA to automatically run the mapping tool
+ at runtime through the
+ <link linkend="openjpa.jdbc.SynchronizeMappings"><literal>
+ openjpa.jdbc.SynchronizeMappings</literal></link> configuration
+ property. Using this property saves you the trouble of running
+ the mapping tool manually, and is meant for use during rapid
+ test/debug cycles.
+ </para>
+ <para>
+ In order to enable automatic runtime mapping, you must first list
+ all your persistent classes as described in
+ <xref linkend="ref_guide_pc_pcclasses"/>.
+ </para>
+ <para>
+ OpenJPA will run the mapping tool on these classes when your
+ application obtains its first <classname>EntityManager</classname>.
+ </para>
+ <para>
+ The <literal>openjpa.jdbc.SynchronizeMappings</literal> property is
+ a plugin string (see <xref linkend="ref_guide_conf_plugins"/>)
+ where the class name is the mapping tool action to invoke, and
+ the properties are the <classname>MappingTool</classname> class'
+ JavaBean properties. These properties correspond go the long
+ versions of the tool's command line flags.
+ </para>
+ <example id="ref_guide_mapping_synchex">
+ <title>Configuring Runtime Forward Mapping</title>
+ <programlisting format="linespecific">
+<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+</programlisting>
+ <para>
+ The setting above corresponds to running the following command:
+ </para>
+ <programlisting format="linespecific">
+mappingtool -a buildSchema -fk true
+</programlisting>
+ </example>
+ </section>
+ </section>
+ <section id="ref_guide_pc_reverse">
+ <title>Reverse Mapping</title>
+ <indexterm zone="ref_guide_pc_reverse">
+ <primary>reverse mapping</primary>
+ </indexterm>
+ <indexterm zone="ref_guide_pc_reverse">
+ <primary>reverse mapping tool</primary>
+ <seealso>reverse mapping</seealso>
+ </indexterm>
+ <indexterm>
+ <primary>mapping metadata</primary>
+ <secondary>reverse mapping</secondary>
+ <see>reverse mapping</see>
+ </indexterm>
+ <para>
+ OpenJPA includes a <emphasis>reverse mapping</emphasis> tool for
+ generating persistent class definitions, complete with
+ metadata, from an existing database schema. You do not
+ have to use the reverse mapping tool to access an existing schema; you
+ are free to write your classes and mappings yourself, as described in
+ <xref linkend="ref_guide_mapping_middle"/>. The reverse mapping tool,
+ however, can give you an excellent starting point from which to grow
+ your persistent classes.
+ </para>
+<!-- ### EJBDOC -->
+ <note>
+ <para>
+ The reverse mapping tool in this release does not yet output JPA
+ annotations. It is limited to JDO metadata output.
+ </para>
+ </note>
+ <para>
+ To use the reverse mapping tool, follow the steps below:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Use the <link linkend="ref_guide_schema_schematool">
+ schema tool</link> to export your current schema
+ to an XML schema file. You can skip this step and the next
+ step if you want to run the reverse mapping tool directly
+ against the database.
+ </para>
+ <example id="ref_guide_pc_reverse_schemagen">
+ <title>Reflection with the Schema Tool</title>
+ <programlisting format="linespecific">
+schematool -a reflect -f schema.xml
+</programlisting>
+ </example>
+ </listitem>
+ <listitem>
+ <para>
+ Examine the generated schema file. JDBC drivers often provide
+ incomplete or faulty metadata, in which case the file will
+ not exactly match the actual schema.
+ Alter the XML file to match the true schema. The XML format
+ for the schema file is described in
+ <xref linkend="ref_guide_schema_xml"/>.
+ </para>
+ <para>
+ After fixing any errors in the schema file, modify the XML
+ to include foreign keys between all relations.
+ The schema tool will have automatically detected existing
+ foreign key constraints; many schemas, however, do not employ
+ database foreign keys for every relation. By manually
+ adding any missing foreign keys, you will give the reverse
+ mapping tool the information it needs to generate the
+ proper relations between the persistent classes it creates.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Run the reverse mapping tool on the finished schema file.
+ If you do not supply the schema file to reverse map, the tool
+ will run directly against the schema in the database. The
+ tool can be run via the included
+ <literal>reversemappingtool</literal> script, or through
+ its Java class,
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/ReverseMappingTool"><classname>org.apache.openjpa.jdbc.meta.ReverseMappingTool</classname></ulink>.
+ </para>
+ <example id="ref_guide_pc_reverse_reversemappingtool">
+ <title>Using the Reverse Mapping Tool</title>
+ <programlisting format="linespecific">
+reversemappingtool -pkg com.xyz -d ~/src -cp customizer.properties schema.xml
+</programlisting>
+ </example>
+ <para>
+ In addition to OpenJPA's <link linkend="ref_guide_conf_devtools">
+ standard configuration flags</link>, including
+ <link linkend="ref_guide_conf_devtools_format">code formatting
+ options</link>, the reverse mapping tool recognizes the
+ following command line arguments:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>-schemas/-s <schema and table names>
+ </literal>: A comma-separated list of schema and
+ table names to reverse map, if no XML schema file is
+ supplied. Each element of the list must follow the
+ naming conventions for the <literal>openjpa.jdbc.Schemas
+ </literal> property described in
+ <xref linkend="ref_guide_schema_info_list"/>. In fact,
+ if this flag is omitted, it defaults to the value of the
+ <literal>Schemas</literal> property. If the
+ <literal>Schemas</literal> property is not defined,
+ all schemas will be reverse-mapped.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-package/-pkg <package name></literal>:
+ The package name of the generated classes. If no
+ package name is given, the generated code will not
+ contain package declarations.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-directory/-d <output directory>
+ </literal>: All generated code and metadata will be
+ written to the directory at this path. If the path does
+ not match the package of a class, the package
+ structure will be created beneath this directory.
+ Defaults to the current directory.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-useSchemaName/-sn <true/t | false/f>
+ </literal>: Set this flag to <literal>true</literal>
+ to include the schema as well as table name in the
+ name of each generated class. This can be useful when
+ dealing with multiple schemas with same-named tables.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-useForeignKeyName/-fkn
+ <true/t | false/f></literal>: Set this flag to
+ <literal>true</literal> if you would like field names
+ for relations to be based on the database foreign key
+ name. By default, relation field names are derived
+ from the name of the related class.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-nullableAsObject/-no <true/t | false/f>
+ </literal>: By default, all non-foreign key columns
+ are mapped to primitives. Set this flag to
+ <literal>true</literal> to generate primitive wrapper
+ fields instead for columns that allow null values.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-blobAsObject/-bo <true/t | false/f>
+ </literal>: By default, all binary columns are mapped
+ to <classname>byte[]</classname> fields. Set this flag
+ to <literal>true</literal> to map them to
+ <classname>Object</classname> fields instead. Note that
+ when mapped this way, the column is presumed to contain
+ a serialized Java object.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-primaryKeyOnJoin/-pkj <true/t | false/f>
+ </literal>: The standard reverse mapping tool behavior
+ is to map all tables with primary keys to persistent
+ classes. If your schema has primary keys on
+ many-many join tables as well, set this flag to
+ <literal>true</literal> to avoid creating classes for
+ those tables.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-inverseRelations/-ir <true/t
+ | false/f></literal>: Set to <literal>false</literal>
+ to prevent the creation of inverse 1-many/1-1
+ relations for every many-1/1-1 relation detected.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-useDatastoreIdentity/-ds
+ <true/t | false/f></literal>: Set to
+ <literal>true</literal> to use datastore identity
+ for tables that have single numeric primary key
+ columns. The tool typically uses application identity
+ for all generated classes.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-useBuiltinIdentityClass/-bic <true/t
+ | false/f></literal>: Set to <literal>false</literal>
+ to prevent the tool from using built-in application
+ identity classes when possible. This will force the
+ tool to to create custom application identity classes
+ even when there is only one primary key column.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-innerIdentityClasses/-inn <true/t
+ | false/f></literal>: Set to <literal>true</literal>
+ to have any generated application identity classes be
+ created as static inner classes within the persistent
+ classes. Defaults to <literal>false</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-identityClassSuffix/-is
+ <suffix></literal>: Suffix to append to class
+ names to form application identity class names, or for
+ inner identity classes, the inner class name.
+ Defaults to <literal>Id</literal>.
+ </para>
+ </listitem>
+<!-- ### EJBDOC : need some EJB equiv -->
+<!-- ### EJBDOC : need some EJB equiv -->
+<!-- ### EJBDOC : need some EJB equiv form XML / anno -->
+ <listitem>
+ <para><literal>-typeMap/-typ <type mapping></literal>:
+ A string that specifies the default Java classes to
+ generate for each SQL type that is seen in the schema.
+ The format is <literal>
+ SQLTYPE1=JavaClass1,SQLTYPE2=JavaClass2</literal>.
+ The SQL type name first looks for a customization
+ based on <literal>SQLTYPE(SIZE,PRECISION)</literal>,
+ then <literal>SQLTYPE(SIZE)</literal>, then
+ <literal>SQLTYPE(SIZE,PRECISION)</literal>. So
+ if a column whose type name is
+ <literal>CHAR</literal> is found, it will first look
+ for the <literal>CHAR(50,0)</literal> type name
+ specification, then it will look for
+ <literal>CHAR(50)</literal>, and finally it will
+ just look for <literal>CHAR</literal>.
+ For example, to generate a char array for
+ every <literal>CHAR</literal> column whose size
+ is exactly 50, and to generate a
+ <literal>short</literal> for every type name of
+ <literal>INTEGER</literal>, you might specify:
+ <literal>CHAR(50)=char[],INTEGER=short</literal>.
+ Note that since various databases report different
+ type names differently, one database's type name
+ specification might not work for another database.
+ Enable <literal>TRACE</literal> level logging on the
+ <literal>MetaData</literal> channel to track which
+ type names OpenJPA is examining.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-customizerClass/-cc
+ <class name></literal>: The full class name of a
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/ReverseCustomizer.html"><classname>org.apache.openjpa.jdbc.meta.ReverseCustomizer</classname></ulink> customization plugin. If you do
+ not specify a reverse customizer of your own, the
+ system defaults to a
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/PropertiesReverseCustomizer.html"><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">
+ below</link>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-customizerProperties/-cp <properties
+ file or resource></literal>: The path or resource
+ name of a properties file to pass to the reverse
+ customizer on initialization.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>-customizer./-c.<property name>
+ <property value></literal>: The given property
+ name will be matched with the corresponding Java bean
+ property in the specified reverse customizer, and set
+ to the given value.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Running the tool will generate <filename>.java</filename> files
+ for each generated class (and its application identity class,
+ if applicable), along with all necessary persistence metadata
+ and mappings.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Examine the generated class, metadata, and mapping
+ information, and modify it as necessary. Remember that
+ the reverse mapping tool only provides a starting point, and
+ you are free to make whatever modifications you like to the
+ code it generates.
+ </para>
+ <para>
+ After you are satisfied with the generated classes and their
+ mappings, you should first compile them with
+ <literal>javac</literal>, <literal>jikes</literal>, or your
+ favorite Java compiler. Make sure the classes and their
+ metadata are located in the directory corresponding to
+ the <literal>-package</literal> flag you gave the reverse
+ mapping tool. Finally, enhance the classes if necessary (see
+ <xref linkend="ref_guide_pc_enhance"/>).
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Your persistent classes are now ready to access your existing schema.
+ </para>
+ <section id="ref_guide_pc_reverse_custom">
+ <title>Customizing Reverse Mapping</title>
+ <para>
+ The <classname>org.apache.openjpa.jdbc.meta.ReverseCustomizer</classname> plugin
+ interface allows you to customze the reverse mapping process. See
+ the class
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/ReverseCustomizer.html">
+ Javadoc</ulink> for details on the hooks that this interface
+ provides. Specify the concrete plugin implementation to use with
+ the <literal>-customizerClass/-cc</literal> command-line flag,
+ described in the preceding section.
+ </para>
+ <para>
+ By default, the reverse mapping tool uses a
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/PropertiesReverseCustomizer.html"><classname>org.apache.openjpa.jdbc.meta.PropertiesReverseCustomizer</classname></ulink>. This customizer allows you to perform
+ relatively simple customizations through the properties file named
+ with the <literal>-customizerProperties</literal> tool flag.
+ The customizer recognizes the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal><table name>.table-type <type>
+ </literal>: Override the default type of the table with
+ name <literal><table name></literal>. Legal values
+ are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>base</literal>: Primary table for a base
+ class.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>secondary</literal>: Secondary table for
+ a class. The table must have a foreign key joining
+ to a class table.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>secondary-outer</literal>: Outer-joined
+ secondary table for a class. The table must have
+ a foreign key joining to a class table.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>association</literal>: Association table.
+ The table must have two foreign keys to class
+ tables.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>collection</literal>: Collection table.
+ The table must have one foreign key to a class
+ table and one data column.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>subclass</literal>: A joined subclass
+ table. The table must have a foreign key to the
+ superclass' table.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>none</literal>: The table should not be
+ reverse-mapped.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para><literal><class name>.rename <new class name>
+ </literal>: Override the given tool-generated name
+ <literal><class name></literal>
+ with a new value. Use full class names, including package.
+ You are free to rename a class to a new package. Specify
+ a value of <literal>none</literal> to reject the class and
+ leave the corresponding table unmapped.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal><table name>.class-name
+ <new class name></literal>: Assign the given
+ fully-qualified class name to the type created from the
+ table with name <literal><table name></literal>.
+ Use a value of <literal>none</literal> to prevent reverse
+ mapping this table. This property can be used in place
+ of the <literal>rename</literal> property.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal><class name>.identity <datastore |
+ builtin | identity class name></literal>: Set this
+ property to <literal>datastore</literal> to use datastore
+ identity for the class <literal><class
+ name></literal>, <literal>builtin</literal> to use
+ a built-in identity class, or the desired
+ application identity class name. Give full class names,
+ including package. You are free to change the package of
+ the identity class this way. If the persistent class has
+ been renamed, use the new class name for this property key.
+ Remember that datastore identity requires a table with a
+ single numeric primary key column, and built-in identity
+ requires a single primary key column of any type.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal><class name>.<field name>.rename
+ <new field name></literal>: Override the
+ tool-generated <literal><field name></literal> in
+ class <literal><class name></literal> with the given
+ name. Use the field owner's full class name in the
+ property key. If the
+ field owner's class was renamed, use the new class name.
+ The property value should be the new field name, without
+ the preceding class name. Use a value of <literal>none
+ </literal> to reject the generated mapping and remove the
+ field from the class.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal><table name>.<column name>.field-name
+ <new field name></literal>: Set the generated field
+ name for the <literal><table name></literal> table's
+ <literal><column name></literal> column. If this is
+ a multi-column mapping, any of the columns can be used.
+ Use a value of <literal>none</literal> to prevent the column
+ and its associated columns from being reverse-mapped.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal><class name>.<field name>.type
+ <field type></literal>: The type to give the named
+ field. Use full class names. If the field or the field's
+ owner class has been renamed, use the new name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal><class name>.<field name>.value
+ </literal>: The initial value for the named field. The
+ given string will be placed as-is in the generated Java
+ code, so be sure it is valid Java. If the
+ field or the field's owner class has been renamed, use the
+ new name.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ All property keys are optional; if not specified, the customizer
+ keeps the default value generated by the reverse mapping tool.
+ </para>
+ <example id="ref_guide_pc_reverse_custom_ex">
+ <title>Customizing Reverse Mapping with Properties</title>
+ <programlisting format="linespecific">
+reversemappingtool -pkg com.xyz -cp custom.properties schema.xml
+</programlisting>
+ <para>
+ Example <filename>custom.properties</filename>:
+ </para>
+ <programlisting format="linespecific">
+com.xyz.TblMagazine.rename: com.xyz.Magazine
+com.xyz.TblArticle.rename: com.xyz.Article
+com.xyz.TblPubCompany.rename: com.xyz.pub.Company
+com.xyz.TblSysInfo.rename: none
+
+com.xyz.Magazine.allArticles.rename: articles
+com.xyz.Magazine.articles.type: java.util.Collection
+com.xyz.Magazine.articles.value: new TreeSet()
+com.xyz.Magazine.identity: datastore
+
+com.xyz.pub.Company.identity: com.xyz.pub.CompanyId
+</programlisting>
+ </example>
+ <para>
+ Your OpenJPA download includes the <classname>
+ PropertiesReverseCustomizer</classname> source code. You can use
+ this code as an example when writing your own customization class.
+ </para>
+ </section>
+ </section>
+ <section id="ref_guide_mapping_middle">
+ <title>Meet-in-the-Middle Mapping</title>
+ <indexterm zone="ref_guide_pc_reverse">
+ <primary>meet-in-the-middle mapping</primary>
+ </indexterm>
+ <indexterm zone="ref_guide_pc_reverse">
+ <primary>reverse mapping tool</primary>
+ <seealso>reverse mapping</seealso>
+ </indexterm>
+ <indexterm>
+ <primary>mapping metadata</primary>
+ <secondary>meet-in-the-middle mapping</secondary>
+ <see>meet-in-the-middle mapping</see>
+ </indexterm>
+ <para>
+ 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. OpenJPA has two
+ tools to aid meet-in-the-middle mapping. First, the OpenJPA Workbench
+ includes a visual interface to wiring your classes and schema together.
+<!-- ### JDO2MIG
+ See <xref linkend="gui_intro"/> to get started with the Workbench.
+-->
+ Second, the mapping tool's <literal>validate</literal> action is useful
+ to meet-in-the-middle mappers. We examined the mapping tool in
+ <xref linkend="ref_guide_mapping_mappingtool"/>. The <literal>validate
+ </literal> 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>
+ <example id="ref_guide_mapping_mappingtool_validate">
+ <title>Validating Mappings</title>
+ <programlisting format="linespecific">
+mappingtool -a validate Magazine.java
+</programlisting>
+ </example>
+ <para>
+ The <literal>buildSchema</literal> action we discussed in
+ <xref linkend="ref_guide_mapping_mappingtool"/> is also somewhat useful
+ during meet-in-the-middle mapping. Unlike the
+ <literal>validate</literal> action, which throws an exception if
+ your mapping data does not match the existing schema,
+ the <literal>buildSchema</literal> action assumes your mapping data
+ is correct, and modifies the schema to match your mappings. This lets
+ you modify your mapping data manually, but saves you the hassle of
+ using your database's tools to bring the schema up-to-date.
+ </para>
+ <para><literal>buildSchema</literal> is the default action when you use
+ JPA mapping defaults (<xref linkend="ref_guide_mapping_defaults"/>).
+ </para>
+ <example id="ref_guide_mapping_middle_buildschema_mid">
+ <title>Creating the Relational Schema from Mappings</title>
+ <programlisting format="linespecific">
+mappingtool Magazine.java
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_mapping_defaults">
+ <title>Mapping Defaults</title>
+ <indexterm zone="ref_guide_mapping_defaults">
+ <primary>MappingDefaults</primary>
+ </indexterm>
+ <indexterm>
+ <primary>mapping metadata</primary>
+ <secondary>defaults</secondary>
+ <see>MappingDefaults</see>
+ </indexterm>
+ <para>
+ The previous sections showed how to use the mapping tool to generate
+ default mappings. But how does the mapping tool know what mappings
+ to generate? The answer lies in the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/MappingDefaults.html"><classname>
+ org.apache.openjpa.jdbc.meta.MappingDefaults</classname></ulink> interface. OpenJPA
+ uses an instance of this interface to decide how to name tables and
+ columns, where to put foreign keys, and generally how to create a
+ schema that matches your object model.
+ </para>
+ <important>
+ <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, or use explicit
+ foreign key mappings as described in
+ <phrase><xref linkend="ref_guide_mapping_jpa_fk"/></phrase>
+
+ .
+ </para>
+ </important>
+ <para>
+ The <link linkend="openjpa.jdbc.MappingDefaults"><literal>
+ openjpa.jdbc.MappingDefaults</literal></link> configuration property
+ controls the <classname>MappingDefaults</classname> interface
+ implementation in use. This is a plugin property (see
+ <xref linkend="ref_guide_conf_plugins"/>), so you can substitute your
+ own implementation or configure the existing ones. OpenJPA includes the
+ following standard implementations:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>jpa</literal>: Provides defaults in compliance with
+ the JPA standard. This is an alias for the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.html"><classname>org.apache.openjpa.persistence.jdbc.PersistenceMappingDefaults
+ </classname></ulink> class. This class extends the
+ <classname>MappingDefaultsImpl</classname> class described
+ below, so it has all the same properties (though with
+ different default values).
+ </para>
+ </listitem>
+ <listitem>
+ <para><phrase><literal>default</literal>:
+ </phrase>
+ This is an alias for the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/MappingDefaultsImpl.html"><classname>org.apache.openjpa.jdbc.meta.MappingDefaultsImpl</classname></ulink> class. This default implementation is highly
+ configurable. It has the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>DefaultMissingInfo</literal>: Whether to
+ default missing column and table names rather than
+ throw an exception. Defaults to false, meaning full
+ mappings are required at runtime and when using
+ mapping tool actions like <literal>buildSchema</literal>
+ and <literal>validate</literal>.
+ </para>
+ <para>
+ The <literal>jpa</literal> plugin above sets this
+ property to true to meet the JPA specification.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>BaseClassStrategy</literal>: The default
+ mapping strategy for base classes. You can specify a
+ built-in strategy alias or the full class name of a
+ <link linkend="ref_guide_mapping_custom_class">
+ custom class strategy</link>. You can also use OpenJPA's
+ plugin format (see
+ <xref linkend="ref_guide_conf_plugins"/>)
+ to pass arguments to the strategy instance. See the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/strats/package-summary.html"><literal>org.apache.openjpa.jdbc.meta.strats</literal></ulink> package
+ for available strategies.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>SubclassStrategy</literal>: The default
+ mapping strategy for subclasses. You can specify a
+ builtin strategy alias or the full class name of a
+ <link linkend="ref_guide_mapping_custom_class">
+ custom class strategy</link>. You can also use OpenJPA's
+ plugin format (see
+ <xref linkend="ref_guide_conf_plugins"/>)
+ to pass arguments to the strategy instance.
+ Common strategies are <literal>vertical</literal> and
+ <literal>flat</literal>, the default. See the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/strats/package-summary.html"><literal>org.apache.openjpa.jdbc.meta.strats</literal></ulink> package
+ for all available strategies.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>VersionStrategy</literal>: The default
+ version strategy for classes without a
+ version field. You can specify a builtin strategy
+ alias or the full class name of a
+ <link linkend="ref_guide_mapping_custom_versdiscrim">
+ custom version strategy</link>. You can also use
+ OpenJPA's plugin format (see
+ <xref linkend="ref_guide_conf_plugins"/>)
+ to pass arguments to the strategy instance.
+ Common strategies are <literal>none</literal>,
+ <literal>state-comparison</literal>, <literal>
+ timestamp</literal>, and <literal>
+ version-number</literal>, the default. See the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/strats/package-summary.html"><literal>org.apache.openjpa.jdbc.meta.strats</literal></ulink> package
+ for all available strategies.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>DiscriminatorStrategy</literal>: The default
+ discriminator strategy when no discriminator value is
+ given. You can specify a builtin strategy alias or
+ the full class name of a
+ <link linkend="ref_guide_mapping_custom_versdiscrim">
+ custom discriminator strategy</link>. You can also use
+ OpenJPA's plugin format (see
+ <xref linkend="ref_guide_conf_plugins"/>)
+ to pass arguments to the strategy instance.
+ Common strategies are <literal>final</literal> for
+ a base class without subclasses, <literal>none
+ </literal> to use joins to subclass tables rather than
+ a discriminator column, and <literal>
+ class-name</literal>, the default. See the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/strats/package-summary.html"><literal>org.apache.openjpa.jdbc.meta.strats</literal></ulink> package
+ for all available strategies.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>FieldStrategies</literal>: This property
+ associates field types with custom strategies. The
+ format of this property is similar to that of plugin
+ strings (see <xref linkend="ref_guide_conf_plugins"/>),
+ without the class name. It is a comma-separated list
+ of key/value pairs, where each key is a possible field
+ type, and each value is itself a plugin string
+ describing the strategy for that type. We present an
+ example below. See
+ <xref linkend="ref_guide_mapping_custom_field"/> for
+ information on custum field strategies.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>ForeignKeyDeleteAction</literal>:
+ The default delete action of foreign keys representing
+ relations to other objects. Recognized values include
+ <literal>restrict</literal>, <literal>cascade</literal>,
+ <literal>null</literal>, <literal>default</literal>.
+ These values correspond exactly to the standard
+ database foreign key actions of the same names.
+ </para>
+ <para>
+ The value <literal>none</literal> tells OpenJPA not to
+ create database foreign keys on relation columns.
+ This is the default.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>JoinForeignKeyDeleteAction</literal>:
+ The defualt delete action of foreign keys that join
+ join secondary, collection, map, or subclass tables to
+ the primary table. Accepts the same values as the
+ <literal>ForeignKeyDeleteAction</literal> property
+ above.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>DeferConstraints</literal>: Whether to use
+ deferred database constraints if possible. Defaults
+ to false.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>IndexLogicalForeignKeys</literal>: Boolean
+ property controlling whether to create indexes on
+ logical foreign keys. Logical foreign keys are
+ columns that represent a link between tables, but
+ have been configured through the <literal>ForeignKey
+ </literal> properties above not to use a physical
+ database foreign key. Defaults to true.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>DataStoreIdColumnName</literal>: The default
+ name of datastore identity columns.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>DiscriminatorColumnName</literal>: The default
+ name of discriminator columns.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>IndexDiscriminator</literal>: Whether to index
+ the discriminator column. Defaults to true.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>VersionColumnName</literal>: The default
+ name of version columns. If you use custom lock groups,
+ this name may be combined with lock group names. See
+ <xref linkend="ref_guide_lock_groups"/> for more
+ information on lock groups.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>IndexVersion</literal>: Whether to index
+ the version column. Defaults to false.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>AddNullIndicator</literal>: Whether to create
+ a synthetic null indicator column for embedded mappings.
+ The null indicator column allows OpenJPA to distinguish
+ between a null embedded object and one with default
+ values for all persistent fields.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>NullIndicatorColumnName</literal>: The default
+ name of synthetic null indicator columns for embedded
+ objects.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>OrderLists</literal>: Whether to create a
+ database ordering column for maintaining the order of
+ persistent lists and arrays. Defaults to true.
+ </para>
+ <para>
+ The <literal>jpa</literal> plugin above sets this
+ property to false in accordance with the JPA
+ specification.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>OrderColumnName</literal>: The default
+ name of collection and array ordering columns.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>StoreEnumOrdinal</literal>:
+ Set to true to store enum fields as numeric ordinal
+ values in the database. The default is to store
+ the enum value name as a string, which is more robust
+ if the Java enum declaration might be rearranged.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>StoreUnmappedObjectIdString</literal>:
+ Set to true to store the stringified identity of
+ related objects when the declared related type is
+ unmapped. By default, OpenJPA stores the related object's
+ primary key value(s). However, this breaks down if
+ different subclasses of the related type use
+ incompatible primary key structures. In that case,
+ stringifying the identity value is the better choice.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The example below turns on foreign key generation during schema
+ creation and associates the <classname>org.mag.data.InfoStruct
+ </classname> field type with the custom <classname>
+ org.mag.mapping.InfoStructHandler</classname> value handler.
+ </para>
+ <example id="ref_guide_mapping_defaults_conf">
+ <title>Configuring Mapping Defaults</title>
+ <programlisting format="linespecific">
+<property name="openjpa.jdbc.MappingDefaults"
+ value="ForeignKeyDeleteAction=restrict,
+ FieldStrategies='org.mag.data.InfoStruct=org.mag.mapping.InfoStructHandler'"/>
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_mapping_factory">
+ <title>Mapping Factory</title>
+ <indexterm zone="ref_guide_mapping_factory">
+ <primary>MappingFactory</primary>
+ </indexterm>
+ <indexterm>
+ <primary>mapping metadata</primary>
+ <secondary>loading and storing</secondary>
+ <see>MappingFactory</see>
+ </indexterm>
+ <para>
+ An important decision in the object-relational mapping process
+ is how and where to store the data necessary to map your persistent
+ classes to the database schema.
+ </para>
+ <para>
+ In JPA, mapping metadata is defined in annotations. Future
+ versions of the JPA drafts will also define a mapping
+ XML format. <xref linkend="jpa_overview_mapping"/> in the
+ JPA Overview describes JPA mapping options.
+ </para>
+ <para><xref linkend="ref_guide_meta_factory"/> introduced OpenJPA's <classname>
+ MetaDataFactory</classname> interface. OpenJPA uses this same interface
+ to abstract the storage and retrieval of mapping information. OpenJPA
+ includes the built-in mapping factories below, and you can create
+ your own factory if you have custom needs. You control which mapping
+ factory OpenJPA uses with the <link linkend="openjpa.jdbc.MappingFactory"><literal>openjpa.jdbc.MappingFactory</literal></link> configuration
+ property.
+ </para>
+ <para>
+ The bundled mapping factories are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>-</literal>: Leaving the <literal>
+ openjpa.jdbc.MappingFactory</literal> property unset allows your
+ metadata factory to take over mappings as well.
+ </para>
+ <para>
+ If you are using the <literal>jpa</literal> metadata factory,
+ OpenJPA will read mapping information from your annotations when
+ you leave the mapping factory unspecified.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <example id="ref_guide_mapping_factory_ejb">
+ <title>Standard JPA Configuration</title>
+ <para>
+ In the standard JPA configuration, the mapping factory
+ is left unset.
+ </para>
+ <programlisting format="linespecific">
+<property name="openjpa.MetaDataFactory" value="jpa"/>
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_mapping_notes_nonstdjoins">
+ <title>Non-Standard Joins</title>
+ <indexterm zone="ref_guide_mapping_notes_nonstdjoins">
+ <primary>joins</primary>
+ <secondary>non-standard</secondary>
+ </indexterm>
+ <para>
+ The JPA Overview's <xref linkend="jpa_overview_mapping"/>
+ explains join mapping. All of the examples in that document,
+ however, use "standard" joins, in that there is one foreign key column
+ for each primary key column in the target table. OpenJPA supports
+ additional join patterns, including partial primary key joins,
+ non-primary key joins, and joins using constant values.
+ </para>
+ <para><indexterm><primary>joins</primary><secondary>partial primary key</secondary></indexterm>
+ In a partial primary key join, the source table only has foreign key
+ columns for a subset of the primary key columns in the target table.
+ So long as this subset of columns correctly identifies the proper
+ row(s) in the referenced table, OpenJPA will function properly.
+ There is no special syntax for expressing a partial primary key join -
+ just do not include column definitions for missing foreign key columns.
+ </para>
+ <para><indexterm><primary>joins</primary><secondary>non-primary key</secondary></indexterm>
+ In a non-primary key join, at least one of the target columns is not a
+ primary key. Once again, OpenJPA supports this join type with the same
+ syntax as a primary key join. There is one restriction, however: each
+ non-primary key column you are joining to must be controlled by a
+ field mapping that implements the
+ <ulink url="../apidocs/org/apache/openjpa/jdbc/meta/Joinable.html"><classname>
+ org.apache.openjpa.jdbc.meta.Joinable</classname></ulink> interface. All built in
+ basic mappings implement this interface, including basic fields of
+ embedded objects. OpenJPA will also respect any custom mappings that
+ implement this interface. See
+ <xref linkend="ref_guide_mapping_custom"/> for an examination of
+ custom mappings.
+ </para>
+ <para><indexterm><primary>joins</primary><secondary>constant</secondary></indexterm>
+ Not all joins consist of only links between columns. In some cases
+ you might have a schema in which one of the join criteria is
+ that a column in the source or target table must have some constant
+ value. OpenJPA calls joins involving constant values <emphasis>constant
+ joins</emphasis>.
+ </para>
+ <para>
+ To form a constant join in JPA mapping, first set the
+ <literal>JoinColumn</literal>'s <literal>name</literal> attribute to
+ the name of the column. If the column with the constant value is the
+ target of the join, give its fully qualified name in the form
+ <literal><table name>.<column name></literal>.
+ Next, set the <literal>referencedColumnName</literal> attribute to the
+ constant value. If the constant value is a string, place it in single
+ quotes to differentiate it from a column name.
+ </para>
+ <mediaobject>
+ <imageobject>
+<!-- PNG image data, 427 x 211 (see README) -->
+ <imagedata fileref="img/joins-constant.png" width="285px"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Consider the tables above. First, we want to join row
+ <literal>T1.R1</literal> to row <literal>T2.R1</literal>. If we just
+ join column <literal>T1.FK</literal> to <literal>T2.PK1</literal>, we
+ will wind up matching both <literal>T2.R1</literal> and <literal>
+ T2.R2</literal>. So in addition to joining <literal>T1.FK</literal>
+ to <literal>T2.PK1</literal>, we also have to specify that
+ <literal>T2.PK2</literal> has the value <literal>a</literal>. Here is
+ how we'd accomplish this in mapping metadata.
+ </para>
+ <programlisting format="linespecific">
+@Entity
+@Table(name="T1")
+public class ...
+{
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name="FK" referencedColumnName="PK1"),
+ @JoinColumn(name="T2.PK2" referencedColumnName="'a'")
+ });
+ private ...;
+}
+</programlisting>
+ <para>
+ Notice that we had to fully qualify the name of column <literal>PK2
+ </literal> because it is in the target table. Also notice that we put
+ single quotes around the constant value so that it won't be confused
+ with a column name. You do not need single quotes for numeric
+ constants. For example, the syntax to join <literal>T1.R2</literal> to
+ <literal>T2.R4</literal> is:
+ </para>
+ <programlisting format="linespecific">
+@Entity
+@Table(name="T1")
+public class ...
+{
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name="FK" referencedColumnName="PK2"),
+ @JoinColumn(name="T2.PK1" referencedColumnName="2")
+ });
+ private ...;
+}
+</programlisting>
+ <para>
+ Finally, from the inverse direction, these joins would look like this:
+ </para>
+ <programlisting format="linespecific">
+@Entity
+@Table(name="T2")
+public class ...
+{
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name="T1.FK" referencedColumnName="PK1"),
+ @JoinColumn(name="PK2" referencedColumnName="'a'")
+ });
+ private ...;
+
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name="T1.FK" referencedColumnName="PK2"),
+ @JoinColumn(name="PK1" referencedColumnName="2")
+ });
+ private ...;
+}
+</programlisting>
+ </section>
+ <section id="ref_guide_mapping_ejb">
+ <title>Additional JPA Mappings</title>
+ <indexterm zone="ref_guide_mapping_ejb">
+ <primary>mapping metadata</primary>
+ <secondary>JPA additions</secondary>
+ </indexterm>
+ <para>
+ OpenJPA supports many persistence strategies beyond those of the JPA
+ specification. <xref linkend="ref_guide_meta_ejb"/>
+ covered the logical metadata for OpenJPA's additional persistence
+ strategies. We now demonstrate how to map entities using these
+ strategies to the database.
+ </para>
+ <section id="ref_guide_mapping_jpa_datastoreid">
+ <title>Datastore Identity Mapping</title>
+ <indexterm zone="ref_guide_mapping_jpa_datastoreid">
+ <primary>datastore identity</primary>
+ <secondary>mapping</secondary>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_jpa_datastoreid">
+ <primary>mapping metadata</primary>
+ <secondary>datastore identity</secondary>
+ <seealso>identity</seealso>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_jpa_datastoreid">
+ <primary>DataStoreIdColumn</primary>
+ <seealso>mapping metadata</seealso>
+ </indexterm>
+ <indexterm>
+ <primary>primary key</primary>
+ </indexterm>
+ <para><xref linkend="ref_guide_pc_oid"/> describes how to use datastore
+ identity in JPA. OpenJPA requires a single numeric
+ primary key column to hold datastore identity values. The
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/DataStoreIdColumn.html"><classname>org.apache.openjpa.persistence.jdbc.DataStoreIdColumn</classname></ulink> annotation customizes the datastore identity column. This
+ annotation has the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>String name</literal>: Defaults to
+ <literal>ID</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>int precision</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String columnDefinition</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>boolean insertable</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>boolean updatable</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ All properties correspond exactly to the same-named properties on
+ the standard <classname>Column</classname> annotation, described in
+ <xref linkend="jpa_overview_mapping_column"/>.
+ </para>
+ <example id="ref_guide_mapping_jpa_datastoreidex">
+ <title>Datastore Identity Mapping</title>
+ <programlisting format="linespecific">
+import org.apache.openjpa.persistence.*;
+import org.apache.openjpa.persistence.jdbc.*;
+
+@Entity
+@Table(name="LOGS")
+@DataStoreIdColumn(name="ENTRY")
+public class LogEntry
+{
+ @Lob
+ private String content;
+
+ ...
+}
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_mapping_jpa_version">
+ <title>Surrogate Version Mapping</title>
+ <indexterm zone="ref_guide_mapping_jpa_datastoreid">
+ <primary>version</primary>
+ <secondary>mapping</secondary>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_jpa_version">
+ <primary>mapping metadata</primary>
+ <secondary>version</secondary>
+ <seealso>version</seealso>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_jpa_version">
+ <primary>VersionColumn</primary>
+ <seealso>mapping metadata</seealso>
+ </indexterm>
+ <para>
+ OpenJPA supports version fields as defined by the JPA
+ specification, but allows you to use a surrogate version column
+ in place of a version field if you like. You map the surrogate
+ version column with the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/VersionColumn.html"><classname>org.apache.openjpa.persistence.jdbc.VersionColumn</classname></ulink>
+ annotation. If you take advantage of OpenJPA's ability to define
+ multiple <link linkend="ref_guide_lock_groups">lock groups</link>,
+ you may have multiple version columns. In that case, use the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/VersionColumns.html"><classname>org.apache.openjpa.persistence.jdbc.VersionColumns</classname></ulink>
+ annotation to declare an array of
+ <classname>VersionColumn</classname> values.
+ Each <classname>VersionColumn</classname> has the following
+ properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>String name</literal>: Defaults to
+ <literal>VERSN</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String lockGroup</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>int length</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>int precision</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>int scale</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String columnDefinition</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>boolean nullable</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>boolean insertable</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>boolean updatable</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <literal>lockGroup</literal> property allows you to specify that
+ a version column is for some lock group other than the default
+ group. See <xref linkend="ref_guide_lock_groups"/> for an example.
+ All other properties correspond exactly to the same-named
+ properties on the standard <classname>Column</classname> annotation,
+ described in <xref linkend="jpa_overview_mapping_column"/>.
+ </para>
+ <para>
+ By default, OpenJPA assumes that surrogate versioning uses a version
+ number strategy. You can choose a different strategy with the
+ <classname>VersionStrategy</classname> annotation described in
+ <xref linkend="version-strategy"/>.
+ </para>
+ </section>
+ <section id="ref_guide_mapping_jpa_columns">
+ <title>Multi-Column Mappings</title>
+ <indexterm zone="ref_guide_mapping_jpa_columns">
+ <primary>mapping metadata</primary>
+ <secondary>column</secondary>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_jpa_columns">
+ <primary>mapping metadata</primary>
+ <secondary>multi-column mappings</secondary>
+ </indexterm>
+ <indexterm zone="ref_guide_mapping_jpa_columns">
+ <primary>Columns</primary>
+ <seealso>mapping metadata</seealso>
+ </indexterm>
+ <para>
+ OpenJPA makes it easy to create multi-column
+ <link linkend="ref_guide_mapping_custom_field">custom
+ mappings</link>. The JPA specification includes a
+ <classname>Column</classname> annotation, but is missing a way to
+ declare multiple columns for a single field. OpenJPA remedies this
+ with the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/Columns.html"><classname>org.apache.openjpa.persistence.jdbc.Columns</classname></ulink>
+ annotation, which contains an array of <classname>Column</classname>
+ values. <xref linkend="ref_guide_mapping_custom_field_conf_extex"/>
+ uses OpenJPA's <classname>Columns</classname> annotation to map a
+ <classname>java.awt.Point</classname> to separate X and Y columns.
+ </para>
+ <para>
+ Remember to annotate custom field types with <classname>
+ Persistent</classname>, as described in
+ <xref linkend="ref_guide_meta_jpa_persistent"/>.
+ </para>
+ </section>
+ <section id="ref_guide_mapping_jpa_fieldjoin">
+ <title>Join Column Attribute Targets</title>
+ <para><xref linkend="jpa_overview_mapping_rel"/> in the JPA
+ Overview introduced you to the <classname>JoinColumn</classname>
+ annotation. A <classname>JoinColumn</classname>'s <literal>
+ referencedColumnName</literal> property declares which column in
+ the table of the related type this join column links to. Suppose,
+ however, that the related type is unmapped, or that it is part of
+ a table-per-class inheritance hierarchy. Each subclass that might
+ be assigned to the field could reside in a different table, and
+ could use entirely different names for its primary key columns.
+ It becomes impossible to supply a single <literal>
+ referencedColumnName</literal> that works for all subclasses.
+ </para>
+ <para>
+ OpenJPA rectifies this by allowing you to declare which
+ <emphasis>attribute</emphasis> in the related type each join column
+ links to, rather than which column. If the attribute is mapped
+ differently in various subclass tables, OpenJPA automatically forms the
+ proper join for the subclass record at hand. The
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/XJoinColumn.html"><classname>org.apache.openjpa.persistence.jdbc.XJoinColumn</classname></ulink>
+ annotation has all the same properties as the standard
+ <classname>JoinColumn</classname> annotation, but adds an
+ additional <literal>referencedAttributeName</literal> property for
+ this purpose. Simply use a <classname>XJoinColumn</classname>
+ in place of a <classname>JoinColumn</classname> whenever you need
+ to access this added functionality.
+ </para>
+ <para>
+ For compound keys, use the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/XJoinColumns.html"><classname>org.apache.openjpa.persistence.jdbc.XJoinColumns</classname></ulink> annotation. The value of this annotation is an array of
+ individual <classname>XJoinColumn</classname>s.
+ </para>
+ </section>
+ <section id="ref_guide_mapping_jpa_embed">
+ <title>Embedded Mapping</title>
+ <para>
+ JPA uses the <classname>AttributeOverride</classname>
+ annotation to override the default mappings of an embeddable
+ class. The JPA Overview details this process in
+ <xref linkend="jpa_overview_mapping_embed"/>. <classname>
+ AttributeOverride</classname>s suffice for simple mappings, but
+ do not allow you to override complex mappings. Also, JPA
+ has no way to differentitate between a null embedded
+ object and one with default values for all of its fields.
+ </para>
+ <para>
+ OpenJPA overcomes these shortcomings with the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/EmbeddedMapping.html"><classname>org.apache.openjpa.persistence.jdbc.EmbeddedMapping</classname></ulink>
+ annotation. This annotation has the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>String nullIndicatorColumnName</literal>: If the
+ named column's value is <literal>NULL</literal>, then the
+ embedded object is assumed to be null. If the named column
+ has a non-<literal>NULL</literal> value, then the embedded
+ object will get loaded and
+ populated with data from the other embedded fields.
+ This property is entirely optional. By default, OpenJPA
+ always assumes the embedded object is non-null, just as
+ in standard JPA mapping.
+ </para>
+ <para>
+ If the column you name does not belong to any fields of the
+ embedded object, OpenJPA will create a synthetic null-indicator
+ column with this name. In fact, you can specify a value of
+ <literal>true</literal> to simply indicate that you want
+ a synthetic null-indicator column, without having to
+ come up with a name for it. A value of <literal>false
+ </literal> signals that you explicitly do not want a
+ null-indicator column created for this mapping (in case you
+ have configured your
+ <link linkend="ref_guide_mapping_defaults">mapping defaults
+ </link> to create one by default).
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>String nullIndicatorFieldName</literal>: Rather
+ than name a null indicator column, you can name a field of
+ the embedded type. OpenJPA will use the column of this field
+ as the null-indicator column.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>MappingOverride[] overrides</literal>: This array
+ allows you to override any mapping of the embedded object.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <classname>EmbeddedMapping</classname>'s
+ <literal>overrides</literal> array serves the same purpose as
+ standard JPA's <classname>AttributeOverride</classname>s and
+ <classname>AssociationOverride</classname>s. In fact,
+ you can also use the <classname>MappingOverride</classname>
+ annotation on an entity class to override a complex mapping of its
+ mapped superclass, just as you can with <classname>
+ AttributeOverride</classname> and <classname>
+ AssociationOverride</classname>s. The <classname>MappingOverrides
+ </classname> annotation, whose value is an array of
+ <classname>MappingOverride</classname>s, allows you to overide
+ multiple mapped superclass mappings.
+ </para>
+ <para>
+ Each
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/MappingOverride.html"><classname>org.apache.openjpa.persistence.jdbc.MappingOverride</classname></ulink>
+ annotation has the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>String name</literal>: The name of the field
+ that is being overridden.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>Column[] columns</literal>: Columns for the new
+ field mapping.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>XJoinColumn[] joinColumns</literal>: Join
+ columns for the new field mapping, if it is a relation
+ field.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>ContainerTable containerTable</literal>: Table
+ for the new collection or map field mapping. We
+ cover collection mappings in
+ <xref linkend="ref_guide_mapping_jpa_coll"/>, and map
+ mappings in
+ <xref linkend="ref_guide_mapping_jpa_map"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>ElementColumn[] elementColumns</literal>: Element
+ columns for the new collection or map field mapping.
+ You will see how to use element columns in
+ <xref linkend="ref_guide_mapping_jpa_coll_cols"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>ElementJoinColumn[] elementJoinColumns</literal>:
+ Element join columns for the new collection or map
+ field mapping. You will see how to use element join
+ columns in
+ <xref linkend="ref_guide_mapping_jpa_coll_joincols"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>KeyColumn[] keyColumns</literal>: Map key
+ columns for the new map field mapping.
+ You will see how to use key columns in
+ <xref linkend="ref_guide_mapping_jpa_map_keycols"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>KeyJoinColumn[] keyJoinColumns</literal>:
+ Key join columns for the new map field mapping.
+ You will see how to use key join columns in
+ <xref linkend="ref_guide_mapping_jpa_map_keyjoincols"/>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following example defines an embeddable <classname>
+ PathCoordinate</classname> class with a custom
+ mapping of a <classname>java.awt.Point</classname> field to two
+ columns. It then defines an entity which embeds a <classname>
+ PointCoordinate</classname> and overrides the default
+ mapping for the point field. The entity also declares that if the
+ <classname>PathCoordinate</classname>'s <literal>siteName</literal>
+ field column is null, it means that no <classname>PathCoordinate
+ </classname> is stored in the embedded record; the owning field
+ will load as null.
+ </para>
+ <example id="ref_guide_mapping_jpa_embedex">
+ <title>Overriding Complex Mappings</title>
+ <programlisting format="linespecific">
+import org.apache.openjpa.persistence.jdbc.*;
+
+@Embeddable
+public class PathCoordinate
+{
+ private String siteName;
+
+ @Persistent
+ @Strategy("com.xyz.openjpa.PointValueHandler")
+ private Point point;
+
+ ...
+}
+
+@Entity
+public class Path
+{
+ @Embedded
+ @EmbeddedMapping(nullIndicatorFieldName="siteName", overrides={
+ @MappingOverride(name="siteName", columns=@Column(name="START_SITE")),
+ @MappingOverride(name="point", columns={
+ @Column(name="START_X"),
+ @Column(name="START_Y")
+ })
+ })
+ private PathCoordinate start;
+
+ ...
+}
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_mapping_jpa_coll">
+ <title>Collections</title>
+ <indexterm zone="ref_guide_mapping_jpa_coll">
+ <primary>mapping metadata</primary>
+ <secondary>collections</secondary>
+ </indexterm>
+ <para>
+ In <xref linkend="ref_guide_meta_jpa_persistent_coll"/>, we
+ explored the <classname>PersistentCollection</classname> annotation
+ for persistent collection fields that aren't a standard
+ <literal>OneToMany</literal> or <literal>ManyToMany</literal>
+ relation. To map these non-standard collections, combine OpenJPA's
+ <classname>ContainerTable</classname> annotation with <classname>
+ ElementColumn</classname>s, <classname>
+ ElementJoinColumn</classname>s, or an <classname>
+ ElementEmbeddedMapping</classname>. We explore the annotations
+ below.
+ </para>
+ <section id="ref_guide_mapping_jpa_coll_table">
+ <title>Container Table</title>
+ <indexterm zone="ref_guide_mapping_jpa_coll_table">
+ <primary>ContainerTable</primary>
+ <seealso>mapping metadata</seealso>
+ </indexterm>
+ <para>
+ The
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/ContainerTable.html"><classname>org.apache.openjpa.persistence.jdbc.ContainerTable</classname></ulink> annotation describes a database table that holds
+ collection (or map) elements. This annotation has the
+ following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>String name</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String catalog</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String schema</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>XJoinColumn[] joinColumns</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ForeignKey joinForeignKey</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Index joinIndex</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <literal>name</literal>, <literal>catalog</literal>,
+ <literal>schema</literal>, and <literal>joinColumns</literal>
+ properties describe the container table and how it joins to
+ the owning entity's table. These properties correspond
+ to the same-named properties on the standard <classname>
+ JoinTable</classname> annotation, described in
+ <xref linkend="jpa_overview_mapping_assoccoll"/>. If left
+ unspecified, the name of the table defaults to
+ the first five characters of the entity table name, plus an
+ underscore, plus the field name. The
+ <literal>joinForeignKey</literal> and <literal>
+ joinIndex</literal> properties override default foreign key
+ and index generation for the join columns. We explore foreign
+ keys and indexes later in this chapter.
+ </para>
+ <para>
+ You may notice that the container table does not define how
+ to store the collection elements. That is left to separate
+ annotations, which are the subject of the next sections.
+ </para>
+ </section>
+ <section id="ref_guide_mapping_jpa_coll_cols">
+ <title>Element Columns</title>
+ <indexterm zone="ref_guide_mapping_jpa_coll_cols">
+ <primary>ElementColumn</primary>
+ <seealso>mapping metadata</seealso>
+ </indexterm>
+ <para>
+ Just as the JPA <classname>Column</classname>
+ annotation maps a simple value (primitive wrapper, <classname>
+ String</classname>, etc), OpenJPA's
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/ElementColumn.html"><classname>org.apache.openjpa.persistence.jdbc.ElementColumn</classname></ulink> annotation maps a simple element value. To map custom
+ multi-column elements, use the
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/ElementColumns.html"><classname>org.apache.openjpa.persistence.jdbc.ElementColumns</classname></ulink> annotation, whose value is an array of <classname>
+ ElementColumn</classname>s.
+ </para>
+ <para>
+ An <classname>ElementColumn</classname> always resides in
+ a container table, so it does not have the <literal>
+ table</literal> property of a standard <classname>
+ Column</classname>. Otherwise, the <classname>ElementColumn
+ </classname> and standard <classname>Column</classname>
+ annotations are equivalent. See
+ <xref linkend="jpa_overview_mapping_column"/> in the JPA
+ Overview for a review of the <classname>Column
+ </classname> annotation.
+ </para>
+ </section>
+ <section id="ref_guide_mapping_jpa_coll_joincols">
+ <title>Element Join Columns</title>
+ <indexterm zone="ref_guide_mapping_jpa_coll_joincols">
+ <primary>ElementJoinColumn</primary>
+ <seealso>mapping metadata</seealso>
+ </indexterm>
+ <para>
+ Element join columns are equivalent to standard JPA
+ join columns, except that they represent a join to a collection
+ or map element entity rather than a direct relation. You
+ represent an element join column with OpenJPA's
+ <ulink url="../apidocs/org/apache/openjpa/persistence/jdbc/ElementJoinColumn.html"><classname>org.apache.openjpa.persistence.jdbc.ElementJoinColumn</classname></ulink> annotation. To declare a compound join, enclose an
+ array of <classname>ElementJoinColumn</classname>s in the
[... 1272 lines stripped ...]