OpenJPA includes a reverse mapping 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 Section 3, “ Meet-in-the-Middle Mapping ”. The reverse mapping tool, however, can give you an excellent starting point from which to grow your persistent classes.
To use the reverse mapping tool, follow the steps below:
Use the schema tool 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.
Example 7.8. Reflection with the Schema Tool
java org.apache.openjpa.jdbc.schema.SchemaTool -a reflect -f schema.xml
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 Section 14, “ XML Schema Format ”.
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.
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 its Java class,
Example 7.9. Using the Reverse Mapping Tool
java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg com.xyz -d ~/src -cp customizer.properties schema.xml
-schemas/-s <schema and table names>: 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
openjpa.jdbc.Schemas property described in
Section 12.1, “
”. In fact, if this flag is
omitted, it defaults to the value of the
Schemas property. If
Schemas property is not defined, all schemas will be
-package/-pkg <package name>: The package name of the
generated classes. If no package name is given, the generated code will not
contain package declarations.
-directory/-d <output directory>: 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.
-metadata/-md <class | package | none>: Specify the
level the metadata should be generated at. Defaults to generating a single
package-level metadata file. Set to
none to disable orm.xml
-annotations/-ann <true/t | false/f>: Set to
generate JPA annotations in generated Java classes.
-accessType/-access <field | property>: Change access
type for generated annotations. Defaults to field access.
-useSchemaName/-sn <true/t | false/f>: Set this flag
true 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.
-useSchemaElement/-se <true/t | false/f>: Set this
false to exclude the schema name from the
@Table annotation in the generated class for each table.
If set to
false, the schema name will also be removed from
the corresponding XML mapping files (orm.xml) that are generated by the tool.
The initialized value is true (in order to preserve backwards compatibility).
-useForeignKeyName/-fkn <true/t | false/f>: Set this
true 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.
-nullableAsObject/-no <true/t | false/f>: By default,
all non-foreign key columns are mapped to primitives. Set this flag to
true to generate primitive wrapper fields instead for columns that
allow null values.
-blobAsObject/-bo <true/t | false/f>: By default, all
binary columns are mapped to
byte fields. Set this flag
true to map them to
instead. Note that when mapped this way, the column is presumed to contain a
serialized Java object.
-primaryKeyOnJoin/-pkj <true/t | false/f>: 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
true to avoid creating classes for
-inverseRelations/-ir <true/t | false/f>: Set to
false to prevent the creation of inverse 1-many/1-1 relations
for every many-1/1-1 relation detected.
-useGenericCollections/-gc <true/t | false/f>: Set to
true to use generic collections on OneToMany and ManyToMany relations.
-useDatastoreIdentity/-ds <true/t | false/f>: Set to
true to use datastore identity for tables that have single
numeric primary key columns. The tool typically uses application identity for
all generated classes.
-useBuiltinIdentityClass/-bic <true/t | false/f>: Set
false to prevent the tool from using built-in application
identity classes when possible. This will force the tool to create custom
application identity classes even when there is only one primary key column.
-innerIdentityClasses/-inn <true/t | false/f>: Set to
true to have any generated application identity classes be
created as static inner classes within the persistent classes. Defaults to
-identityClassSuffix/-is <suffix>: Suffix to append to
class names to form application identity class names, or for inner identity
classes, the inner class name. Defaults to
-typeMap/-typ <type mapping>: A string that specifies
the default Java classes to generate for each SQL type that is seen in the
schema. The format is
. The SQL type name first looks for a customization based on
SQLTYPE. So if a column whose type name is
CHAR is found, it will first look for the
CHAR(50,0) type name specification, then it will look for
CHAR(50), and finally it will just look for
For example, to generate a char array for every
whose size is exactly 50, and to generate a
short for every
type name of
INTEGER, you might specify:
CHAR(50)=char,INTEGER=short. Note that since various databases
report different type names differently, one database's type name specification
might not work for another database. Enable
logging on the
MetaData channel to track which type names
OpenJPA is examining.
-customizerClass/-cc <class name>: The full class name
customization plugin. If you do not specify a reverse customizer of your own,
the system defaults to a
PropertiesReverseCustomizer. This customizer
allows you to specify simple customization options in the properties file given
-customizerProperties flag below. We present the
available property keys
-customizerProperties/-cp <properties file or resource>
: The path or resource name of a properties file to pass to the reverse
customizer on initialization.
-customizer./-c.<property name> <property value>
: The given property name will be matched with the corresponding Java bean
property in the specified reverse customizer, and set to the given value.
Running the tool will generate
.java files for each
generated class (and its application identity class, if applicable), along with
JPA annotations (if enabled by setting
orm.xml file (if not disabled with
-metadata none) containing the corresponding persistence metadata.
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.
After you are satisfied with the generated classes and their mappings, you
should first compile the classes with
jikes, or your favorite Java compiler. Make sure the classes are
located in the directory corresponding to the
you gave the reverse mapping tool. Next, if you have generated an
orm.xml, move that file to a
within a directory in your classpath. Finally, enhance the classes
if necessary (see Section 2, “
Your persistent classes are now ready to access your existing schema.
interface allows you to customize the reverse mapping process. See the class
Javadoc for details on the hooks that this interface provides. Specify
the concrete plugin implementation to use with the
-customizerClass/-cc command-line flag, described in the preceding
By default, the reverse mapping tool uses a
. This customizer allows you to perform relatively simple
customizations through the properties file named with the
-customizerProperties tool flag. The customizer recognizes the
<table name>.table-type <type>: Override the
default type of the table with name
Legal values are:
base: Primary table for a base class.
secondary: Secondary table for a class. The table must have
a foreign key joining to a class table.
secondary-outer: Outer-joined secondary table for a class.
The table must have a foreign key joining to a class table.
association: Association table. The table must have two
foreign keys to class tables.
collection: Collection table. The table must have one
foreign key to a class table and one data column.
subclass: A joined subclass table. The table must have a
foreign key to the superclass' table.
none: The table should not be reverse-mapped.
<class name>.rename <new class name>: Override
the given tool-generated name
<class name> 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
none to reject the class
and leave the corresponding table unmapped.
<table name>.class-name <new class name>: Assign
the given fully-qualified class name to the type created from the table with
<table name>. Use a value of
to prevent reverse mapping this table. This property can be used in
place of the
<class name>.identity <datastore | builtin | identity class
name>: Set this property to
datastore to use
datastore identity for the class
builtin 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.
<class name>.<field name>.rename <new field name>
: Override the tool-generated
<field name> in
<class name> 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
to reject the generated mapping and remove the field from the class.
<table name>.<column name>.field-name <new field
name>: Set the generated field name for the
<column name> column. If
this is a multi-column mapping, any of the columns can be used. Use a value of
none to prevent the column and its associated columns from
<class name>.<field name>.type <field type>
: 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.
<class name>.<field name>.value: 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.
All property keys are optional; if not specified, the customizer keeps the default value generated by the reverse mapping tool.
Example 7.10. Customizing Reverse Mapping with Properties
java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg com.xyz -cp custom.properties schema.xml
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