diff --git a/openjpa-project/src/doc/manual/ref_guide_mapping.xml b/openjpa-project/src/doc/manual/ref_guide_mapping.xml index 7547ebdde..fa3105e9e 100644 --- a/openjpa-project/src/doc/manual/ref_guide_mapping.xml +++ b/openjpa-project/src/doc/manual/ref_guide_mapping.xml @@ -1,3032 +1,3328 @@ - - - - - Mapping - - - - mapping metadata - - - -The JPA Overview's explains -object-relational mapping under JPA. This chapter reviews the mapping utilities -OpenJPA provides and examines OpenJPA features that go beyond the JPA -specification. - -
- - Forward Mapping - - - - forward mapping - - - - - mapping tool - - - forward mapping - - - - - mapping metadata - - - forward mapping - - - forward mapping - - - -Forward mapping is the process of creating mappings and -their corresponding database schema from your object model. OpenJPA supports -forward mapping through the mapping tool. The next section -presents several common mapping tool use cases. You can invoke the tool through -its Java class, - -org.apache.openjpa.jdbc.meta.MappingTool. - - - - describes the mapping -tool Ant task. - - - - - Using the Mapping Tool - - -java org.apache.openjpa.jdbc.meta.MappingTool Magazine.java - - - -In addition to the universal flags of the -configuration framework, the -mapping tool accepts the following command line arguments: - - - - --schemaAction/-sa <add | refresh | drop | build | retain | reflect | createDB | dropDB | import | export | none> -: The action to take on the schema. These options correspond to the -same-named actions on the schema tool described in -. Actions can be composed in a -comma-separated list. 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 add action or the -build action. Otherwise you may end up inadvertently -dropping schema components that are used by classes you are not -currently running the tool over. - - - - --schemaFile/-sf <stdout | output file>: 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 schema tool. - - - - --sqlFile/-sql <stdout | output file>: Use this option -to write the planned schema modifications to a SQL script rather than modify the -database. Combine this with a schemaAction of build - to generate a script that recreates the schema for the current -mappings, even if the schema already exists. - - - - --dropTables/-dt <true/t | false/f>: Corresponds to the -same-named option on the schema tool. - - - - --dropSequences/-dsq <true/t | false/f>: Corresponds to -the same-named option on the schema tool. - - - - --openjpaTables/-ot <true/t | false/f>: Corresponds to -the same-named option on the schema tool. - - - - --ignoreErrors/-i <true/t | false/f>: Corresponds to -the same-named option on the schema tool. - - - - --schemas/-s <schema and table names>: Corresponds to -the same-named option on the schema tool. This option is ignored if -readSchema is not set to true. - - - - --readSchema/-rs <true/t | false/f>: Set this option to -true 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. - - - - --primaryKeys/-pk <true/t | false/f>: Whether to read -and manipulate primary key information of existing tables. Defaults to false. - - - - --foreignKeys/-fk <true/t | false/f>: 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. - - - - --indexes/-ix <true/t | false/f>: 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. - - - - --sequences/-sq <true/t | false/f>: Whether to -manipulate sequences. Defaults to true. - - - - --meta/-m <true/t | false/f>: Whether the given action -applies to metadata rather than or in addition to mappings. - - - - -The mapping tool also uses an -action/-a argument to specify -the action to take on each class. The available actions are: - - - - -buildSchema: 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 -informative exception. - - - - -validate: 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. - - - - -Each additional argument to the tool should be one of: - - - - -The full name of a persistent class. - - - - -The .java file for a persistent class. - - - - -The .class file of a persistent class. - - - - -If you do not supply any arguments to the mapping tool, it will run on the -classes in your persistent classes list (see -). - - -The mappings generated by the mapping tool are stored by the system -mapping factory. -discusses your mapping factory options. - -
- - Using the Mapping Tool - - - - mapping tool - - - use cases - - - -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 -of the JPA Overview to override any unsatisfactory defaults, run the -mapping tool on your persistent classes. The default buildSchema - mapping tool action manipulates the database schema to -match your mappings. It fails if any of your mappings don't match your object -model. - - - - Creating the Relational Schema from Mappings - - -java org.apache.openjpa.jdbc.meta.MappingTool Magazine.java - - - -To drop the schema for a persistent class, set the mapping tool's -schemaAction to drop. - - - - Refreshing entire schema and cleaning out tables - - - - testing - - - Rebuild mappings and clean tables - - - -java org.apache.openjpa.jdbc.meta.MappingTool -sa add,deleteTableContents - - - - - Dropping Mappings and Association Schema - - -java org.apache.openjpa.jdbc.meta.MappingTool -sa drop Magazine.java - - -
-
- - Generating DDL SQL - - - - mapping tool - - - DDL generation - - - - - DDL - - - with mapping tool - - - -The examples below show how to use the mapping tool to generate DDL SQL scripts, -rather than modifying the database directly. - - - - Create DDL for Current Mappings - - -This example uses your existing mappings to determine the needed schema, then -writes the SQL to create that schema to create.sql. - - -java org.apache.openjpa.jdbc.meta.MappingTool -sa build -sql create.sql Magazine.java - - - - - Create DDL to Update Database for Current Mappings - - -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 -update.sql. - - -java org.apache.openjpa.jdbc.meta.MappingTool -sql update.sql Magazine.java - - -
-
- - Runtime Forward Mapping - - - - forward mapping - - - automatic runtime mapping - - - - - mapping metadata - - - automatic runtime mapping - - - -You can configure OpenJPA to automatically run the mapping tool at runtime -through the -openjpa.jdbc.SynchronizeMappings 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. - - -In order to enable automatic runtime mapping, you must first list all your -persistent classes as described in . - - -OpenJPA will run the mapping tool on these classes when your application obtains -its first EntityManager. - - -The openjpa.jdbc.SynchronizeMappings property is a plugin -string (see ) where the class -name is the mapping tool action to invoke, and the properties are the -MappingTool class' JavaBean properties. These properties -correspond go the long versions of the tool's command line flags. - - - - Configuring Runtime Forward Mapping - - -<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> - - -The setting above corresponds to running the following command: - - -java org.apache.openjpa.jdbc.meta.MappingTool -a buildSchema -fk true - - -
-
-
- - Reverse Mapping - - - - reverse mapping - - - - - reverse mapping tool - - - reverse mapping - - - - - mapping metadata - - - reverse mapping - - - reverse mapping - - - -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 . 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. - - - - 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 . - - -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, - -org.apache.openjpa.jdbc.meta.ReverseMappingTool. - - - - Using the Reverse Mapping Tool - - -java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg com.xyz -d ~/src -cp customizer.properties schema.xml - - - -In addition to OpenJPA's standard -configuration flags, including -code formatting options, -the reverse mapping tool recognizes the following command line arguments: - - - - --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 -for the openjpa.jdbc.Schemas property described in -. In fact, if this flag is -omitted, it defaults to the value of the Schemas property. If -the Schemas property is not defined, all schemas will be -reverse-mapped. - - - - --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 -generation. - - - - --annotations/-ann <true/t | false/f>: Set to true 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 -to 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. - - - - --useForeignKeyName/-fkn <true/t | false/f>: Set this -flag to 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 -to true to map them to Object fields -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 -those tables. - - - - --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 (requires -JDK 1.5 or higher). - - - - --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 -to false 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. - - - - --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 -false. - - - - --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 Id. - - - - --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 SQLTYPE1=JavaClass1,SQLTYPE2=JavaClass2 -. The SQL type name first looks for a customization based on -SQLTYPE(SIZE,PRECISION), then SQLTYPE(SIZE), then -SQLTYPE(SIZE,PRECISION). 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 CHAR. -For example, to generate a char array for every CHAR column -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 TRACE level -logging on the MetaData channel to track which type names -OpenJPA is examining. - - - - --customizerClass/-cc <class name>: The full class name -of a - -org.apache.openjpa.jdbc.meta.ReverseCustomizer -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 -with the -customizerProperties flag below. We present the -available property keys -below. - - - - --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 -annotations true), -or an 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 javac, -jikes, or your favorite Java compiler. Make sure the classes are -located in the directory corresponding to the -package flag -you gave the reverse mapping tool. Next, if you have generated an -orm.xml, move that file to a META-INF directory -within a directory in your classpath. Finally, enhance the classes -if necessary (see ). - - - - -Your persistent classes are now ready to access your existing schema. - -
- - Customizing Reverse Mapping - - -The org.apache.openjpa.jdbc.meta.ReverseCustomizer plugin -interface allows you to customze 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 -section. - - -By default, the reverse mapping tool uses a - -org.apache.openjpa.jdbc.meta.PropertiesReverseCustomizer -. This customizer allows you to perform relatively simple -customizations through the properties file named with the --customizerProperties tool flag. The customizer recognizes the -following properties: - - - - -<table name>.table-type <type>: Override the -default type of the table with name <table 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 -name <table name>. Use a value of none - to prevent reverse mapping this table. This property can be used in -place of the rename property. - - - - -<class name>.identity <datastore | builtin | identity class -name>: Set this property to datastore to use -datastore identity for the class <class name>, -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 <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 none -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 <table -name> table's <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 -being reverse-mapped. - - - - -<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. - - - - Customizing Reverse Mapping with Properties - - -java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg com.xyz -cp custom.properties schema.xml - - -Example custom.properties: - - -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 - - -
-
-
- - Meet-in-the-Middle Mapping - - - - meet-in-the-middle mapping - - - - - reverse mapping tool - - - reverse mapping - - - - - mapping metadata - - - meet-in-the-middle mapping - - - meet-in-the-middle mapping - - - -In the meet-in-the-middle -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 validate action is useful to meet-in-the-middle -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. - - - - Validating Mappings - - -java org.apache.openjpa.jdbc.meta.MappingTool -a validate Magazine.java - - - -The buildSchema action we discussed in - is also somewhat useful -during meet-in-the-middle mapping. Unlike the validate -action, which throws an exception if your mapping data does not match the -existing schema, the buildSchema 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. - -
-
- - Mapping Defaults - - - - MappingDefaults - - - - - mapping metadata - - - defaults - - - MappingDefaults - - - -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 - -org.apache.openjpa.jdbc.meta.MappingDefaults -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. - - - -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 ), -or use explicit foreign key mappings as described in -. - - - -The -openjpa.jdbc.MappingDefaults configuration property controls -the MappingDefaults interface implementation in use. This -is a plugin property (see ), so -you can substitute your own implementation or configure the existing ones. -OpenJPA includes the following standard implementations: - - - - -jpa: Provides defaults in compliance with the JPA standard. -This is an alias for the - -org.apache.openjpa.persistence.jdbc.PersistenceMappingDefaults - class. This class extends the -MappingDefaultsImpl class described below, so it has all the same -properties (though with different default values), as well as: - - - - -PrependFieldNameToJoinTableInverseJoinColumns: Whether to -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. - - - - - - -default: This is an alias for the - -org.apache.openjpa.jdbc.meta.MappingDefaultsImpl -class. This default implementation is highly configurable. It has the following -properties: - - - - -DefaultMissingInfo: Whether to default missing column and -table names rather than throw an exception. If set to false, full explicit -mappings are required at runtime and when using mapping tool actions like -buildSchema and validate. - - - - -BaseClassStrategy: The default mapping strategy for base -classes. You can specify a built-in strategy alias or the full class name of a -custom class strategy. -You can also use OpenJPA's plugin format (see -) to pass arguments to the -strategy instance. See the - -org.apache.openjpa.jdbc.meta.strats package for -available strategies. - - - - -SubclassStrategy: The default mapping strategy for -subclasses. You can specify a builtin strategy alias or the full class name of a - custom class strategy. -You can also use OpenJPA's plugin format (see -) to pass arguments to the -strategy instance. Common strategies are vertical and -flat, the default. See the - -org.apache.openjpa.jdbc.meta.strats package for all -available strategies. - - - - -VersionStrategy: The default version strategy for classes -without a version field. You can specify a builtin strategy alias or the full -class name of a custom -version strategy. You can also use OpenJPA's plugin format (see -) to pass arguments to the -strategy instance. Common strategies are none, -state-comparison, timestamp, and -version-number, the default. See the - -org.apache.openjpa.jdbc.meta.strats package for all -available strategies. - - - - -DiscriminatorStrategy: The default discriminator strategy -when no discriminator value is given. You can specify a builtin strategy alias -or the full class name of a - custom discriminator -strategy. You can also use OpenJPA's plugin format (see -) to pass arguments to the -strategy instance. Common strategies are final for a base -class without subclasses, none to use joins to subclass -tables rather than a discriminator column, and class-name, -the default. See the - -org.apache.openjpa.jdbc.meta.strats package for all -available strategies. - - - - -FieldStrategies: This property associates field types with -custom strategies. The format of this property is similar to that of plugin -strings (see ), 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 - for information on custum -field strategies. - - - - -ForeignKeyDeleteAction: The default delete action of foreign -keys representing relations to other objects. Recognized values include -restrict, cascade, null -, default. These values correspond exactly to the standard -database foreign key actions of the same names. - - -The value none tells OpenJPA not to create database foreign -keys on relation columns. This is the default. - - - - -JoinForeignKeyDeleteAction: 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 -ForeignKeyDeleteAction property above. - - - - -DeferConstraints: Whether to use deferred database -constraints if possible. Defaults to false. - - - - -IndexLogicalForeignKeys: 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 ForeignKey properties above not to use a physical -database foreign key. Defaults to true. - - - - -DataStoreIdColumnName: The default name of datastore -identity columns. - - - - -DiscriminatorColumnName: The default name of discriminator -columns. - - - - -IndexDiscriminator: Whether to index the discriminator -column. Defaults to true. - - - - -VersionColumnName: The default name of version columns. - - - - -IndexVersion: Whether to index the version column. Defaults -to false. - - - - -AddNullIndicator: 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. - - - - -NullIndicatorColumnName: The default name of synthetic null -indicator columns for embedded objects. - - - - -OrderLists: Whether to create a database ordering column for -maintaining the order of persistent lists and arrays. - - - - -OrderColumnName: The default name of collection and array -ordering columns. - - - - -StoreEnumOrdinal: 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. - - - - -StoreUnmappedObjectIdString: 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. - - - - - - -The example below turns on foreign key generation during schema creation and -associates the org.mag.data.InfoStruct field type with -the custom org.mag.mapping.InfoStructHandler value -handler. - - - - Configuring Mapping Defaults - - -<property name="openjpa.jdbc.MappingDefaults" - value="ForeignKeyDeleteAction=restrict, - FieldStrategies='org.mag.data.InfoStruct=org.mag.mapping.InfoStructHandler'"/> - - -
-
- - Mapping Factory - - - - MappingFactory - - - - - mapping metadata - - - loading and storing - - - MappingFactory - - - -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. - - - introduced OpenJPA's -MetaDataFactory 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 - -openjpa.jdbc.MappingFactory configuration property. - - -The bundled mapping factories are: - - - - --: Leaving the openjpa.jdbc.MappingFactory - property unset allows your metadata factory to take over mappings as -well. If you are using the default jpa metadata factory, -OpenJPA will read mapping information from your annotations and -orm.xml when you leave the mapping factory unspecified. - - - - - - Standard JPA Configuration - - -In the standard JPA configuration, the mapping factory is left unset. - - -<property name="openjpa.MetaDataFactory" value="jpa"/> - - -
-
- - Non-Standard Joins - - - - joins - - - non-standard - - - -The JPA Overview's 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. - - - - - joins - - - partial primary key - - -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. - - - - - joins - - - non-primary key - - -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 - -org.apache.openjpa.jdbc.meta.Joinable 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 for an -examination of custom mappings. - - - - - joins - - - constant - - -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 constant joins. - - -To form a constant join in JPA mapping, first set the JoinColumn -'s name 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 <table name>.<column name> -. Next, set the referencedColumnName attribute to -the constant value. If the constant value is a string, place it in single quotes -to differentiate it from a column name. - - - - - - - - - -Consider the tables above. First, we want to join row T1.R1 -to row T2.R1. If we just join column T1.FK -to T2.PK1, we will wind up matching both T2.R1 - and T2.R2. So in addition to joining -T1.FK to T2.PK1, we also have to specify that -T2.PK2 has the value a. Here is how we'd -accomplish this in mapping metadata. - - -@Entity -@Table(name="T1") -public class ... { - - @ManyToOne - @JoinColumns({ - @JoinColumn(name="FK" referencedColumnName="PK1"), - @JoinColumn(name="T2.PK2" referencedColumnName="'a'") - }); - private ...; -} - - -Notice that we had to fully qualify the name of column PK2 -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 -T1.R2 to T2.R4 is: - - -@Entity -@Table(name="T1") -public class ... { - - @ManyToOne - @JoinColumns({ - @JoinColumn(name="FK" referencedColumnName="PK2"), - @JoinColumn(name="T2.PK1" referencedColumnName="2") - }); - private ...; -} - - -Finally, from the inverse direction, these joins would look like this: - - -@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 ...; -} - -
-
- - Additional JPA Mappings - - - - mapping metadata - - - JPA additions - - - -OpenJPA supports many persistence strategies beyond those of the JPA -specification. covered the logical -metadata for OpenJPA's additional persistence strategies. We now demonstrate how -to map entities using these strategies to the database. - -
- - Datastore Identity Mapping - - - - datastore identity - - - mapping - - - - - mapping metadata - - - datastore identity - - - identity - - - - - DataStoreIdColumn - - - mapping metadata - - - - - primary key - - - - describes how to use datastore identity -in JPA. OpenJPA requires a single numeric primary key column to hold datastore -identity values. The - -org.apache.openjpa.persistence.jdbc.DataStoreIdColumn - annotation customizes the datastore identity column. This annotation -has the following properties: - - - - -String name: Defaults to ID. - - - - -int precision - - - - -String columnDefinition - - - - -boolean insertable - - - - -boolean updatable - - - - -All properties correspond exactly to the same-named properties on the standard -Column annotation, described in -. - - - - Datastore Identity Mapping - - -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; - - ... -} - - -
-
- - Surrogate Version Mapping - - - - version - - - mapping - - - - - mapping metadata - - - version - - - version - - - - - VersionColumn - - - mapping metadata - - - -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 - -org.apache.openjpa.persistence.jdbc.VersionColumn -annotation. You can also use the - -org.apache.openjpa.persistence.jdbc.VersionColumns - annotation to declare an array of VersionColumn -values. Each VersionColumn has the following properties: - - - - -String name: Defaults to VERSN. - - - - -int length - - - - -int precision - - - - -int scale - - - - -String columnDefinition - - - - -boolean nullable - - - - -boolean insertable - - - - -boolean updatable - - - - -All properties correspond exactly to the same-named properties on the standard -Column annotation, described in -. - - -By default, OpenJPA assumes that surrogate versioning uses a version number -strategy. You can choose a different strategy with the -VersionStrategy annotation described in -. - -
-
- - Multi-Column Mappings - - - - mapping metadata - - - column - - - - - mapping metadata - - - multi-column mappings - - - - - Columns - - - mapping metadata - - - -OpenJPA makes it easy to create multi-column -custom mappings. The JPA -specification includes a Column annotation, but is -missing a way to declare multiple columns for a single field. OpenJPA remedies -this with the - -org.apache.openjpa.persistence.jdbc.Columns -annotation, which contains an array of Column values. - - -Remember to annotate custom field types with Persistent, -as described in . - -
-
- - Join Column Attribute Targets - - - in the JPA Overview introduced -you to the JoinColumn annotation. A -JoinColumn's referencedColumnName 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 -referencedColumnName that works for all subclasses. - - -OpenJPA rectifies this by allowing you to declare which attribute - 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 - -org.apache.openjpa.persistence.jdbc.XJoinColumn -annotation has all the same properties as the standard JoinColumn - annotation, but adds an additional -referencedAttributeName property for this purpose. Simply use a -XJoinColumn in place of a JoinColumn - whenever you need to access this added functionality. - - -For compound keys, use the - -org.apache.openjpa.persistence.jdbc.XJoinColumns -annotation. The value of this annotation is an array of individual -XJoinColumns. - -
-
- - Embedded Mapping - - -JPA uses the AttributeOverride annotation to override the -default mappings of an embeddable class. The JPA Overview details this process -in . -AttributeOverrides 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. - - -OpenJPA overcomes these shortcomings with the - -org.apache.openjpa.persistence.jdbc.EmbeddedMapping - annotation. This annotation has the following properties: - - - - -String nullIndicatorColumnName: If the named column's value -is NULL, then the embedded object is assumed to be null. If -the named column has a non- NULL 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. - - -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 true to simply indicate that you -want a synthetic null-indicator column, without having to come up with a name -for it. A value of false signals that you explicitly do not -want a null-indicator column created for this mapping (in case you have -configured your mapping defaults - to create one by default). - - - - -String nullIndicatorFieldName: 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. - - - - -MappingOverride[] overrides: This array allows you to -override any mapping of the embedded object. - - - - -The EmbeddedMapping's overrides array -serves the same purpose as standard JPA's AttributeOverride -s and AssociationOverride s. In fact, you can -also use the MappingOverride annotation on an entity -class to override a complex mapping of its mapped superclass, just as you can -with AttributeOverride and -AssociationOverride s. The MappingOverrides -annotation, whose value is an array of MappingOverride s, -allows you to overide multiple mapped superclass mappings. - - -Each - -org.apache.openjpa.persistence.jdbc.MappingOverride - annotation has the following properties: - - - - -String name: The name of the field that is being overridden. - - - - -Column[] columns: Columns for the new field mapping. - - - - -XJoinColumn[] joinColumns: Join columns for the new field -mapping, if it is a relation field. - - - - -ContainerTable containerTable: Table for the new collection -or map field mapping. We cover collection mappings in -, and map mappings in -. - - - - -ElementJoinColumn[] elementJoinColumns: Element join columns -for the new collection or map field mapping. You will see how to use element -join columns in . - - - - -The following example defines an embeddable PathCoordinate - class with a custom mapping of a java.awt.Point - field to two columns. It then defines an entity which embeds a - PointCoordinate and overrides the default mapping for -the point field. The entity also declares that if the PathCoordinate -'s siteName field column is null, it means that -no PathCoordinate is stored in the embedded record; the -owning field will load as null. - - - - Overriding Complex Mappings - - -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; - - ... -} - - -
-
- - Collections - - - - mapping metadata - - - collections - - - -In , we explored the -PersistentCollection annotation for persistent collection -fields that aren't a standard OneToMany or -ManyToMany relation. To map these non-standard collections, combine -OpenJPA's ContainerTable annotation with -ElementJoinColumns. -We explore the annotations below. - -
- - Container Table - - - - ContainerTable - - - mapping metadata - - - -The - -org.apache.openjpa.persistence.jdbc.ContainerTable - annotation describes a database table that holds collection (or map) -elements. This annotation has the following properties: - - - - -String name - - - - -String catalog - - - - -String schema - - - - -XJoinColumn[] joinColumns - - - - -ForeignKey joinForeignKey - - - - -Index joinIndex - - - - -The name, catalog, schema -, and joinColumns 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 JoinTable -annotation, described in -. 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 joinForeignKey and joinIndex -properties override default foreign key and index generation for the join -columns. We explore foreign keys and indexes later in this chapter. - - -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. - -
-
- - Element Join Columns - - - - ElementJoinColumn - - - mapping metadata - - - -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 - -org.apache.openjpa.persistence.jdbc.ElementJoinColumn - annotation. To declare a compound join, enclose an array of -ElementJoinColumns in the - -org.apache.openjpa.persistence.jdbc.ElementJoinColumns - annotation. - - -An ElementJoinColumn always resides in a container table, -so it does not have the table property of a standard - JoinColumn. Like XJoinColumns -above, ElementJoinColumns can reference a linked -attribute rather than a static linked column. Otherwise, the -ElementJoinColumn and standard JoinColumn -annotations are equivalent. See -in the JPA Overview for a review of the JoinColumn -annotation. - -
-
- - Order Column - - - - OrderColumn - - - mapping metadata - - - -Relational databases do not guarantee that records are returned in insertion -order. If you want to make sure that your collection elements are loaded in the -same order they were in when last stored, you must declare an order column. -OpenJPA's - -org.apache.openjpa.persistence.jdbc.OrderColumn -annotation has the following properties: - - - - -String name: Defaults to ORDR. - - - - -boolean enabled - - - - -int precision - - - - -String columnDefinition - - - - -boolean insertable - - - - -boolean updatable - - - - -Order columns are always in the container table. You can explicitly turn off -ordering (if you have enabled it by default via your - mapping defaults) by setting -the enabled property to false. All other -properties correspond exactly to the same-named properties on the standard -Column annotation, described in -. - -
-
-
- - One-Sided One-Many Mapping - - - - mapping metadata - - - collections - - - JPA one-sided one-many - - - -The previous section covered the use of ElementJoinColumn -annotations in conjunction with a ContainerTable for -mapping collections to dedicate tables. ElementJoinColumn -s, however, have one additional use: to create a one-sided one-many mapping. -Standard JPA supports OneToMany fields without a -mappedBy inverse, but only by mapping these fields to a -JoinTable (see - in the JPA Overview for -details). Often, you'd like to create a one-many association based on an inverse -foreign key (logical or actual) in the table of the related type. - - - - - - - - - -Consider the model above. Subscription has a collection -of LineItem s, but LineItem has -no inverse relation to Subscription. To retrieve all of -the LineItem records for a Subscription -, we join the SUB_ID inverse foreign key column -in the LINE_ITEM table to the primary key column of the -SUB table. The example below shows how to represent this -model in mapping annotations. Note that OpenJPA automatically assumes an inverse -foreign key mapping when element join columns are given, but no container or -join table is given. - - - - One-Sided One-Many Mapping - - -package org.mag.subscribe; - -import org.apache.openjpa.persistence.jdbc.*; - -@Entity -@Table(name="LINE_ITEM", schema="CNTRCT") -public class LineItem { - ... -} - -@Entity -@Table(name="SUB", schema="CNTRCT") -public class Subscription { - - @Id private long id; - - @OneToMany - @ElementJoinColumn(name="SUB_ID", target="ID") - private Collection<LineItem> items; - - ... -} - - -
-
- - Maps - - - - mapping metadata - - - maps - - - -We detailed the ContainerTable annotation in -. Custom map mappings may -also use this annotation to represent a map table. - -
-
- - Indexes and Constraints - - -OpenJPA uses index information during schema generation to index the proper -columns. OpenJPA uses foreign key and unique constraint information during -schema creation to generate the proper database constraints, and also at runtime -to order SQL statements to avoid constraint violations while maximizing SQL -batch size. - - -OpenJPA assumes certain columns have indexes or constraints based on your -mapping defaults, as detailed in . -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. - -
- - Indexes - - - - mapping metadata - - - indexes - - - - - indexes - - - -The -org.apache.openjpa.persistence.jdbc.Index -annotation represents an index on the columns of a field. It is also used within -the ContainerTable - annotation to index join columns. -To index the columns of a collection element, use the - - org.apache.openjpa.persistence.jdbc.ElementIndex -annotation. These annotations have the following properties: - - - - -boolean enabled: Set this property to false - to explicitly tell OpenJPA not to index these columns, when OpenJPA -would otherwise do so. - - - - -String name: The name of the index. OpenJPA will choose a -name if you do not provide one. - - - - -boolean unique: Whether to create a unique index. Defaults -to false. - - - -
-
- - Foreign Keys - - - - mapping metadata - - - foreign keys - - - - - foreign keys - - - -The -org.apache.openjpa.persistence.jdbc.ForeignKey -annotation represents a foreign key on the columns of a field. It is also used -within the -ContainerTable annotation to set a database foreign key on -join columns. To set a constraint to the columns of a collection element, use -the - - org.apache.openjpa.persistence.jdbc.ElementForeignKey - annotation. These annotations have the following properties: - - - - -boolean enabled: Set this property to false - to explicitly tell OpenJPA not to set a foreign key on these columns, -when OpenJPA would otherwise do so. - - - - -String name: The name of the foreign key. OpenJPA will -choose a name if you do not provide one, or will create an anonymous key. - - - - -boolean deferred: Whether to create a deferred key if -supported by the database. - - - - -ForeignKeyAction deleteAction: Value from the - -org.apache.openjpa.persistence.jdbc.ForeignKeyAction - enum identifying the desired delete action. Defaults to -RESTRICT. - - - - -ForeignKeyAction updateAction: Value from the - -org.apache.openjpa.persistence.jdbc.ForeignKeyAction - enum identifying the desired update action. Defaults to -RESTRICT. - - - - -Keep in mind that OpenJPA uses foreign key information at runtime to avoid -constraint violations; it is important, therefore, that your -mapping defaults and foreign -key annotations combine to accurately reflect your existing database -constraints, or that you configure OpenJPA to reflect on your database schema -to discover existing foreign keys (see -). - -
-
- - Unique Constraints - - - - mapping metadata - - - unique constraints - - - - - unique constraints - - - -The -org.apache.openjpa.persistence.jdbc.Unique -annotation represents a unqiue constraint on the columns of a field. It is more -convenient than using the uniqueConstraints property of -standard JPA Table and SecondaryTable - annotations, because you can apply it directly to the constrained -field. The Unique annotation has the following -properties: - - - - -boolean enabled: Set this property to false - to explicitly tell OpenJPA not to constrain these columns, when -OpenJPA would otherwise do so. - - - - -String name: The name of the constraint. OpenJPA will choose -a name if you do not provide one, or will create an anonymous constraint. - - - - -boolean deferred: Whether to create a deferred constraint if -supported by the database. - - - -
-
-
-
- - Mapping Limitations - - - - mapping metadata - - - limitations - - - -The following sections outline the limitations OpenJPA places on specific -mapping strategies. - -
- - Table Per Class - - - - mapping metadata - - - limitations - - - table-per-class - - - -Table-per-class inheritance mapping has the following limitations: - - - - -You cannot traverse polymorphic relations to non-leaf classes in a -table-per-class inheritance hierarchy in queries. - - - - -You cannot map a one-sided polymorphic relation to a non-leaf class in a -table-per-class inheritance hierarchy using an inverse foreign key. - - - - -You cannot use an order column in a polymorphic relation to a non-leaf class in -a table-per-class inheritance hierarchy mapped with an inverse foreign key. - - - - -Table-per-class hierarchies impose limitations on eager fetching. See -. - - - - - -Non-polymorphic relations do not suffer from these limitations. You can declare -a non-polymorphic relation using the extensions described in -. - - -
-
-
- - Mapping Extensions - - -Mapping extensions allow you to access OpenJPA-specific functionality from your -mappings. Note that all extensions below are specific to mappings. If you store -your mappings separately from your persistence metadata, these extensions must -be specified along with the mapping information, not the persistence metadata -information. - -
- - Class Extensions - - -OpenJPA recognizes the following class extensions. - -
- - Subclass Fetch Mode - - - - mapping metadata - - - extensions - - - subclass fetch mode - - - eager fetching - - - -This extension specifies how to eagerly fetch subclass state. It overrides the -global -openjpa.jdbc.SubclassFetchMode property. Set the JPA - -org.apache.openjpa.persistence.jdbc.SubclassFetchMode - annotation to a value from the - -org.apache.openjpa.persistence.jdbc.EagerFetchType - enum: JOIN, PARALLEL, or -NONE. See - for a discussion of eager fetching. - -
-
- - Strategy - - - - mapping metadata - - - extensions - - - strategy - - - custom mapping - - - -The -org.apache.openjpa.persistence.jdbc.Strategy -class annotation allows you to specify a custom mapping strategy for your class. -See for information on custom -mappings. - -
-
- - Discriminator Strategy - - - - mapping metadata - - - extensions - - - discriminator strategy - - - custom mapping - - - -The - -org.apache.openjpa.persistence.jdbc.DiscriminatorStrategy - class annotation allows you to specify a custom discriminator strategy. -See for information on custom -mappings. - -
-
- - Version Strategy - - - - mapping metadata - - - extensions - - - version strategy - - - custom mapping - - - -The - -org.apache.openjpa.persistence.jdbc.VersionStrategy - class annotation allows you to specify a custom version strategy. See - for information on custom -mappings. - -
-
-
- - Field Extensions - - -OpenJPA recognizes the following field extensions. - -
- - Eager Fetch Mode - - - - mapping metadata - - - extensions - - - eager fetch mode - - - eager fetching - - - -This extension specifies how to eagerly fetch related objects. It overrides the -global -openjpa.jdbc.EagerFetchMode property. Set the JPA - -org.apache.openjpa.persistence.jdbc.EagerFetchMode - annotation to a value from the - -org.apache.openjpa.persistence.jdbc.EagerFetchType - enum: JOIN, PARALLEL, or -NONE. See - for a discussion of eager fetching. - -
-
- - Nonpolymorphic - - - - mapping metadata - - - extensions - - - nonpolymorphic - - - -All fields in Java are polymorphic. If you declare a field of type T -, you can assign any subclass of T to the field as -well. This is very convenient, but can make relation traversal very inefficient -under some inheritance strategies. It can even make querying across the field -impossible. Often, you know that certain fields do not need to be entirely -polymorphic. By telling OpenJPA about such fields, you can improve the -efficiency of your relations. - - - -OpenJPA also includes the type metadata extension for -narrowing the declared type of a field. See . - - - -OpenJPA defines the following extensions for nonpolymorphic values: - - - - - -org.apache.openjpa.persistence.jdbc.Nonpolymorphic - - - - - - -org.apache.openjpa.persistence.jdbc.ElementNonpolymorphic - - - - - -The value of these extensions is a constant from the - -org.apache.openjpa.persistence.jdbc.NonpolymorphicType - enumeration. The default value, EXACT, indicates -that the relation will always be of the exact declared type. A value of -JOINABLE, on the other hand, means that the relation might -be to any joinable subclass of the declared type. This value only excludes -table-per-class subclasses. - -
-
- - Class Criteria - - - - mapping metadata - - - extensions - - - class criteria - - - joins - - - - - joins - - - class criteria - - - -This family of boolean extensions determines whether OpenJPA will use the -expected class of related objects as criteria in the SQL it issues to load a -relation field. Typically, this is not needed. The foreign key values uniquely -identify the record for the related object. Under some rare mappings, however, -you may need to consider both foreign key values and the expected class of the -related object - for example, if you have an inverse relation that shares the -foreign key with another inverse relation to an object of a different subclass. -In these cases, set the proper class critera extension to true - to force OpenJPA to append class criteria to its select SQL. - - -OpenJPA defines the following class criteria annotations for field relations and -array or collection element relations, respectively: - - - - - -org.apache.openjpa.persistence.jdbc.ClassCriteria - - - - - -org.apache.openjpa.persistence.jdbc.ElementClassCriteria - - - - -
-
- - Strategy - - - - mapping metadata - - - extensions - - - strategy - - - custom mapping - - - -OpenJPA's - -org.apache.openjpa.persistence.jdbc.Strategy -extension allows you to specify a custom mapping -strategy or value handler for a field. See - for information on custom -mappings. - -
-
-
-
- - Custom Mappings - - - - custom mapping - - - - - mapping metadata - - - custom mapping - - - custom mapping - - - -In OpenJPA, you are not limited to the set of standard mappings defined by the -specification. OpenJPA allows you to define custom class, discriminator, -version, and field mapping strategies with all the power of OpenJPA's built-in -strategies. - -
- - Custom Class Mapping - - -To create a custom class mapping, write an implementation of the - -org.apache.openjpa.jdbc.meta.ClassStrategy -interface. You will probably want to extend one of the existing abstract or -concrete strategies in the org.apache.openjpa.jdbc.meta.strats - package. - - -The -org.apache.openjpa.persistence.jdbc.Strategy -annotation allows you to declare a custom class mapping strategy in JPA mapping -metadata. Set the value of the annotation to the full class name of your custom -strategy. You can configure your strategy class' bean properties using -OpenJPA's plugin syntax, detailed in . - -
-
- - Custom Discriminator and Version Strategies - - -To define a custom discriminator or version strategy, implement the - -org.apache.openjpa.jdbc.meta.DiscriminatorStrategy - or - -org.apache.openjpa.jdbc.meta.VersionStrategy -interface, respectively. You might extend one of the existing abstract or -concrete strategies in the org.apache.openjpa.jdbc.meta.strats - package. - - -OpenJPA includes the - -org.apache.openjpa.persistence.jdbc.DiscriminatorStrategy - and - -org.apache.openjpa.persistence.jdbc.VersionStrategy - class annotations for declaring a custom discriminator or version -strategy in JPA mapping metadata. Set the string value of these annotations to -the full class name of your implementation, or to the class name or alias of an -existing OpenJPA implementation. - - -As with custom class mappings, you can configure your strategy class' bean -properties using OpenJPA's plugin syntax, detailed in -. - -
-
- - Custom Field Mapping - - - - custom mapping - - - field mapping - - - -While custom class, discriminator, and version mapping can be useful, custom -field mappings are far more common. OpenJPA offers two types of custom field -mappings: value handlers, and full custom field strategies. The following -sections examine each. - -
- - Value Handlers - - - - custom mapping - - - field mapping - - - value handler - - - -Value handlers make it trivial to map any type that you can break down into one -or more simple values. All value handlers implement the -org.apache.openjpa.jdbc.meta.ValueHandler interface; see its - Javadoc - for details. Also, examine the built-in handlers in the -src/openjpa/jdbc/meta/strats directory of your OpenJPA source -distribution. Use these functional implementations as examples when you -create your own value handlers. - -
-
- - Field Strategies - - - - custom mapping - - - field mapping - - - field strategy - - - -OpenJPA interacts with persistent fields through the - -org.apache.openjpa.jdbc.meta.FieldStrategy interface. You -can implement this interface yourself to create a custom field strategy, or -extend one of the existing abstract or concrete strategies in the -org.apache.openjpa.jdbc.meta.strats package. Creating a custom field -strategy is more difficult than writing a custom value handler, but gives you -more freedom in how you interact with the database. - -
-
- - Configuration - - - - custom mapping - - - field mapping - - - configuration - - - -OpenJPA gives you two ways to configure your custom field mappings. The -FieldStrategies property of the built-in -MappingDefaults 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. - described mapping -defaults in detail. - - -Your other option is to explicitly install a custom value handler or strategy on -a particular field. To do so, specify the full name of your implementation class -in the proper mapping metadata extension. OpenJPA includes the - -org.apache.openjpa.persistence.jdbc.Strategy -annotation. You can configure the named strategy or handler's bean -properties in these extensions using OpenJPA's plugin format (see -). - -
-
-
-
- - Orphaned Keys - - -Unless you apply database foreign key constraints extensively, it is possible to -end up with orphaned keys in your database. For example, suppose -Magazinem has a reference to Article -a. If you delete a without -nulling m's reference, m's database -record will wind up with an orphaned key to the non-existent a - record. - - - -One way of avoiding orphaned keys is to use dependent -fields. - - - -OpenJPA's -openjpa.OrphanedKeyAction configuration property controls what -action to take when OpenJPA encounters an orphaned key. You can set this plugin -string (see ) to a custom -implementation of the - - org.apache.openjpa.event.OrphanedKeyAction -interface, or use one of the built-in options: - - - - -log: This is the default setting. This option logs a message -for each orphaned key. It is an alias for the - -org.apache.openjpa.event.LogOrphanedKeyAction -class, which has the following additional properties: - - - - -Channel: The channel to log to. Defaults to -openjpa.Runtime. - - - - -Level: The level to log at. Defaults to WARN -. - - - - - - -exception: Throw an -EntityNotFoundException when OpenJPA discovers an -orphaned key. This is an alias for the - -org.apache.openjpa.event.ExceptionOrphanedKeyAction - class. - - - - -none: Ignore orphaned keys. This is an alias for the - -org.apache.openjpa.event.NoneOrphanedKeyAction -class. - - - - - - Custom Logging Orphaned Keys - - -<property name="openjpa.OrphanedKeyAction" value="log(Channel=Orphans, Level=DEBUG)"/> - - -
-
+ + + + + Mapping + + + + mapping metadata + + + +The JPA Overview's explains +object-relational mapping under JPA. This chapter reviews the mapping utilities +OpenJPA provides and examines OpenJPA features that go beyond the JPA +specification. + +
+ + Forward Mapping + + + + forward mapping + + + + + mapping tool + + + forward mapping + + + + + mapping metadata + + + forward mapping + + + forward mapping + + + +Forward mapping is the process of creating mappings and +their corresponding database schema from your object model. OpenJPA supports +forward mapping through the mapping tool. The next section +presents several common mapping tool use cases. You can invoke the tool through +its Java class, + +org.apache.openjpa.jdbc.meta.MappingTool. + + + + describes the mapping +tool Ant task. + + + + + Using the Mapping Tool + + +java org.apache.openjpa.jdbc.meta.MappingTool Magazine.java + + + +In addition to the universal flags of the +configuration framework, the +mapping tool accepts the following command line arguments: + + + + +-schemaAction/-sa <add | refresh | drop | build | retain | reflect | createDB | dropDB | import | export | none> +: The action to take on the schema. These options correspond to the +same-named actions on the schema tool described in +. Actions can be composed in a +comma-separated list. 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 add action or the +build action. Otherwise you may end up inadvertently +dropping schema components that are used by classes you are not +currently running the tool over. + + + + +-schemaFile/-sf <stdout | output file>: 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 schema tool. + + + + +-sqlFile/-sql <stdout | output file>: Use this option +to write the planned schema modifications to a SQL script rather than modify the +database. Combine this with a schemaAction of build + to generate a script that recreates the schema for the current +mappings, even if the schema already exists. + + + + +-dropTables/-dt <true/t | false/f>: Corresponds to the +same-named option on the schema tool. + + + + +-dropSequences/-dsq <true/t | false/f>: Corresponds to +the same-named option on the schema tool. + + + + +-openjpaTables/-ot <true/t | false/f>: Corresponds to +the same-named option on the schema tool. + + + + +-ignoreErrors/-i <true/t | false/f>: Corresponds to +the same-named option on the schema tool. + + + + +-schemas/-s <schema and table names>: Corresponds to +the same-named option on the schema tool. This option is ignored if +readSchema is not set to true. + + + + +-readSchema/-rs <true/t | false/f>: Set this option to +true 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. + + + + +-primaryKeys/-pk <true/t | false/f>: Whether to read +and manipulate primary key information of existing tables. Defaults to false. + + + + +-foreignKeys/-fk <true/t | false/f>: 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. + + + + +-indexes/-ix <true/t | false/f>: 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. + + + + +-sequences/-sq <true/t | false/f>: Whether to +manipulate sequences. Defaults to true. + + + + +-meta/-m <true/t | false/f>: Whether the given action +applies to metadata rather than or in addition to mappings. + + + + +The mapping tool also uses an -action/-a argument to specify +the action to take on each class. The available actions are: + + + + +buildSchema: 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 +informative exception. + + + + +validate: 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. + + + + +Each additional argument to the tool should be one of: + + + + +The full name of a persistent class. + + + + +The .java file for a persistent class. + + + + +The .class file of a persistent class. + + + + +If you do not supply any arguments to the mapping tool, it will run on the +classes in your persistent classes list (see +). + + +The mappings generated by the mapping tool are stored by the system +mapping factory. +discusses your mapping factory options. + +
+ + Using the Mapping Tool + + + + mapping tool + + + use cases + + + +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 +of the JPA Overview to override any unsatisfactory defaults, run the +mapping tool on your persistent classes. The default buildSchema + mapping tool action manipulates the database schema to +match your mappings. It fails if any of your mappings don't match your object +model. + + + + Creating the Relational Schema from Mappings + + +java org.apache.openjpa.jdbc.meta.MappingTool Magazine.java + + + +To drop the schema for a persistent class, set the mapping tool's +schemaAction to drop. + + + + Refreshing entire schema and cleaning out tables + + + + testing + + + Rebuild mappings and clean tables + + + +java org.apache.openjpa.jdbc.meta.MappingTool -sa add,deleteTableContents + + + + + Dropping Mappings and Association Schema + + +java org.apache.openjpa.jdbc.meta.MappingTool -sa drop Magazine.java + + +
+
+ + Generating DDL SQL + + + + mapping tool + + + DDL generation + + + + + DDL + + + with mapping tool + + + +The examples below show how to use the mapping tool to generate DDL SQL scripts, +rather than modifying the database directly. + + + + Create DDL for Current Mappings + + +This example uses your existing mappings to determine the needed schema, then +writes the SQL to create that schema to create.sql. + + +java org.apache.openjpa.jdbc.meta.MappingTool -sa build -sql create.sql Magazine.java + + + + + Create DDL to Update Database for Current Mappings + + +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 +update.sql. + + +java org.apache.openjpa.jdbc.meta.MappingTool -sql update.sql Magazine.java + + +
+
+ + Runtime Forward Mapping + + + + forward mapping + + + automatic runtime mapping + + + + + mapping metadata + + + automatic runtime mapping + + + +You can configure OpenJPA to automatically run the mapping tool at runtime +through the +openjpa.jdbc.SynchronizeMappings 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. + + +In order to enable automatic runtime mapping, you must first list all your +persistent classes as described in . + + +OpenJPA will run the mapping tool on these classes when your application obtains +its first EntityManager. + + +The openjpa.jdbc.SynchronizeMappings property is a plugin +string (see ) where the class +name is the mapping tool action to invoke, and the properties are the +MappingTool class' JavaBean properties. These properties +correspond go the long versions of the tool's command line flags. + + + + Configuring Runtime Forward Mapping + + +<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> + + +The setting above corresponds to running the following command: + + +java org.apache.openjpa.jdbc.meta.MappingTool -a buildSchema -fk true + + +
+
+
+ + Reverse Mapping + + + + reverse mapping + + + + + reverse mapping tool + + + reverse mapping + + + + + mapping metadata + + + reverse mapping + + + reverse mapping + + + +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 . 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. + + + + 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 . + + +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, + +org.apache.openjpa.jdbc.meta.ReverseMappingTool. + + + + Using the Reverse Mapping Tool + + +java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg com.xyz -d ~/src -cp customizer.properties schema.xml + + + +In addition to OpenJPA's standard +configuration flags, including +code formatting options, +the reverse mapping tool recognizes the following command line arguments: + + + + +-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 +for the openjpa.jdbc.Schemas property described in +. In fact, if this flag is +omitted, it defaults to the value of the Schemas property. If +the Schemas property is not defined, all schemas will be +reverse-mapped. + + + + +-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 +generation. + + + + +-annotations/-ann <true/t | false/f>: Set to true 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 +to 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. + + + + +-useForeignKeyName/-fkn <true/t | false/f>: Set this +flag to 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 +to true to map them to Object fields +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 +those tables. + + + + +-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 (requires +JDK 1.5 or higher). + + + + +-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 +to false 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. + + + + +-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 +false. + + + + +-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 Id. + + + + +-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 SQLTYPE1=JavaClass1,SQLTYPE2=JavaClass2 +. The SQL type name first looks for a customization based on +SQLTYPE(SIZE,PRECISION), then SQLTYPE(SIZE), then +SQLTYPE(SIZE,PRECISION). 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 CHAR. +For example, to generate a char array for every CHAR column +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 TRACE level +logging on the MetaData channel to track which type names +OpenJPA is examining. + + + + +-customizerClass/-cc <class name>: The full class name +of a + +org.apache.openjpa.jdbc.meta.ReverseCustomizer +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 +with the -customizerProperties flag below. We present the +available property keys +below. + + + + +-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 -annotations true), +or an 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 javac, +jikes, or your favorite Java compiler. Make sure the classes are +located in the directory corresponding to the -package flag +you gave the reverse mapping tool. Next, if you have generated an +orm.xml, move that file to a META-INF directory +within a directory in your classpath. Finally, enhance the classes +if necessary (see ). + + + + +Your persistent classes are now ready to access your existing schema. + +
+ + Customizing Reverse Mapping + + +The org.apache.openjpa.jdbc.meta.ReverseCustomizer plugin +interface allows you to customze 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 +section. + + +By default, the reverse mapping tool uses a + +org.apache.openjpa.jdbc.meta.PropertiesReverseCustomizer +. This customizer allows you to perform relatively simple +customizations through the properties file named with the +-customizerProperties tool flag. The customizer recognizes the +following properties: + + + + +<table name>.table-type <type>: Override the +default type of the table with name <table 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 +name <table name>. Use a value of none + to prevent reverse mapping this table. This property can be used in +place of the rename property. + + + + +<class name>.identity <datastore | builtin | identity class +name>: Set this property to datastore to use +datastore identity for the class <class name>, +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 <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 none +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 <table +name> table's <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 +being reverse-mapped. + + + + +<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. + + + + Customizing Reverse Mapping with Properties + + +java org.apache.openjpa.jdbc.meta.ReverseMappingTool -pkg com.xyz -cp custom.properties schema.xml + + +Example custom.properties: + + +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 + + +
+
+
+ + Meet-in-the-Middle Mapping + + + + meet-in-the-middle mapping + + + + + reverse mapping tool + + + reverse mapping + + + + + mapping metadata + + + meet-in-the-middle mapping + + + meet-in-the-middle mapping + + + +In the meet-in-the-middle +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 validate action is useful to meet-in-the-middle +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. + + + + Validating Mappings + + +java org.apache.openjpa.jdbc.meta.MappingTool -a validate Magazine.java + + + +The buildSchema action we discussed in + is also somewhat useful +during meet-in-the-middle mapping. Unlike the validate +action, which throws an exception if your mapping data does not match the +existing schema, the buildSchema 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. + +
+
+ + Mapping Defaults + + + + MappingDefaults + + + + + mapping metadata + + + defaults + + + MappingDefaults + + + +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 + +org.apache.openjpa.jdbc.meta.MappingDefaults +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. + + + +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 ), +or use explicit foreign key mappings as described in +. + + + +The +openjpa.jdbc.MappingDefaults configuration property controls +the MappingDefaults interface implementation in use. This +is a plugin property (see ), so +you can substitute your own implementation or configure the existing ones. +OpenJPA includes the following standard implementations: + + + + +jpa: Provides defaults in compliance with the JPA standard. +This is an alias for the + +org.apache.openjpa.persistence.jdbc.PersistenceMappingDefaults + class. This class extends the +MappingDefaultsImpl class described below, so it has all the same +properties (though with different default values), as well as: + + + + +PrependFieldNameToJoinTableInverseJoinColumns: Whether to +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. + + + + + + +default: This is an alias for the + +org.apache.openjpa.jdbc.meta.MappingDefaultsImpl +class. This default implementation is highly configurable. It has the following +properties: + + + + +DefaultMissingInfo: Whether to default missing column and +table names rather than throw an exception. If set to false, full explicit +mappings are required at runtime and when using mapping tool actions like +buildSchema and validate. + + + + +BaseClassStrategy: The default mapping strategy for base +classes. You can specify a built-in strategy alias or the full class name of a +custom class strategy. +You can also use OpenJPA's plugin format (see +) to pass arguments to the +strategy instance. See the + +org.apache.openjpa.jdbc.meta.strats package for +available strategies. + + + + +SubclassStrategy: The default mapping strategy for +subclasses. You can specify a builtin strategy alias or the full class name of a + custom class strategy. +You can also use OpenJPA's plugin format (see +) to pass arguments to the +strategy instance. Common strategies are vertical and +flat, the default. See the + +org.apache.openjpa.jdbc.meta.strats package for all +available strategies. + + + + +VersionStrategy: The default version strategy for classes +without a version field. You can specify a builtin strategy alias or the full +class name of a custom +version strategy. You can also use OpenJPA's plugin format (see +) to pass arguments to the +strategy instance. Common strategies are none, +state-comparison, timestamp, and +version-number, the default. See the + +org.apache.openjpa.jdbc.meta.strats package for all +available strategies. + + + + +DiscriminatorStrategy: The default discriminator strategy +when no discriminator value is given. You can specify a builtin strategy alias +or the full class name of a + custom discriminator +strategy. You can also use OpenJPA's plugin format (see +) to pass arguments to the +strategy instance. Common strategies are final for a base +class without subclasses, none to use joins to subclass +tables rather than a discriminator column, and class-name, +the default. See the + +org.apache.openjpa.jdbc.meta.strats package for all +available strategies. + + + + +FieldStrategies: This property associates field types with +custom strategies. The format of this property is similar to that of plugin +strings (see ), 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 + for information on custum +field strategies. + + + + +ForeignKeyDeleteAction: The default delete action of foreign +keys representing relations to other objects. Recognized values include +restrict, cascade, null +, default. These values correspond exactly to the standard +database foreign key actions of the same names. + + +The value none tells OpenJPA not to create database foreign +keys on relation columns. This is the default. + + + + +JoinForeignKeyDeleteAction: 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 +ForeignKeyDeleteAction property above. + + + + +DeferConstraints: Whether to use deferred database +constraints if possible. Defaults to false. + + + + +IndexLogicalForeignKeys: 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 ForeignKey properties above not to use a physical +database foreign key. Defaults to true. + + + + +DataStoreIdColumnName: The default name of datastore +identity columns. + + + + +DiscriminatorColumnName: The default name of discriminator +columns. + + + + +IndexDiscriminator: Whether to index the discriminator +column. Defaults to true. + + + + +VersionColumnName: The default name of version columns. + + + + +IndexVersion: Whether to index the version column. Defaults +to false. + + + + +AddNullIndicator: 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. + + + + +NullIndicatorColumnName: The default name of synthetic null +indicator columns for embedded objects. + + + + +OrderLists: Whether to create a database ordering column for +maintaining the order of persistent lists and arrays. + + + + +OrderColumnName: The default name of collection and array +ordering columns. + + + + +StoreEnumOrdinal: 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. + + + + +StoreUnmappedObjectIdString: 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. + + + + + + +The example below turns on foreign key generation during schema creation and +associates the org.mag.data.InfoStruct field type with +the custom org.mag.mapping.InfoStructHandler value +handler. + + + + Configuring Mapping Defaults + + +<property name="openjpa.jdbc.MappingDefaults" + value="ForeignKeyDeleteAction=restrict, + FieldStrategies='org.mag.data.InfoStruct=org.mag.mapping.InfoStructHandler'"/> + + +
+
+ + Mapping Factory + + + + MappingFactory + + + + + mapping metadata + + + loading and storing + + + MappingFactory + + + +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. + + + introduced OpenJPA's +MetaDataFactory 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 + +openjpa.jdbc.MappingFactory configuration property. + + +The bundled mapping factories are: + + + + +-: Leaving the openjpa.jdbc.MappingFactory + property unset allows your metadata factory to take over mappings as +well. If you are using the default jpa metadata factory, +OpenJPA will read mapping information from your annotations and +orm.xml when you leave the mapping factory unspecified. + + + + + + Standard JPA Configuration + + +In the standard JPA configuration, the mapping factory is left unset. + + +<property name="openjpa.MetaDataFactory" value="jpa"/> + + +
+
+ + Non-Standard Joins + + + + joins + + + non-standard + + + +The JPA Overview's 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. + + + + + joins + + + partial primary key + + +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. + + + + + joins + + + non-primary key + + +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 + +org.apache.openjpa.jdbc.meta.Joinable 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 for an +examination of custom mappings. + + + + + joins + + + constant + + +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 constant joins. + + +To form a constant join in JPA mapping, first set the JoinColumn +'s name 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 <table name>.<column name> +. Next, set the referencedColumnName attribute to +the constant value. If the constant value is a string, place it in single quotes +to differentiate it from a column name. + + + + + + + + + +Consider the tables above. First, we want to join row T1.R1 +to row T2.R1. If we just join column T1.FK +to T2.PK1, we will wind up matching both T2.R1 + and T2.R2. So in addition to joining +T1.FK to T2.PK1, we also have to specify that +T2.PK2 has the value a. Here is how we'd +accomplish this in mapping metadata. + + +@Entity +@Table(name="T1") +public class ... { + + @ManyToOne + @JoinColumns({ + @JoinColumn(name="FK" referencedColumnName="PK1"), + @JoinColumn(name="T2.PK2" referencedColumnName="'a'") + }); + private ...; +} + + +Notice that we had to fully qualify the name of column PK2 +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 +T1.R2 to T2.R4 is: + + +@Entity +@Table(name="T1") +public class ... { + + @ManyToOne + @JoinColumns({ + @JoinColumn(name="FK" referencedColumnName="PK2"), + @JoinColumn(name="T2.PK1" referencedColumnName="2") + }); + private ...; +} + + +Finally, from the inverse direction, these joins would look like this: + + +@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 ...; +} + +
+
+ + Additional JPA Mappings + + + + mapping metadata + + + JPA additions + + + +OpenJPA supports many persistence strategies beyond those of the JPA +specification. covered the logical +metadata for OpenJPA's additional persistence strategies. We now demonstrate how +to map entities using these strategies to the database. + +
+ + Datastore Identity Mapping + + + + datastore identity + + + mapping + + + + + mapping metadata + + + datastore identity + + + identity + + + + + DataStoreIdColumn + + + mapping metadata + + + + + primary key + + + + describes how to use datastore identity +in JPA. OpenJPA requires a single numeric primary key column to hold datastore +identity values. The + +org.apache.openjpa.persistence.jdbc.DataStoreIdColumn + annotation customizes the datastore identity column. This annotation +has the following properties: + + + + +String name: Defaults to ID. + + + + +int precision + + + + +String columnDefinition + + + + +boolean insertable + + + + +boolean updatable + + + + +All properties correspond exactly to the same-named properties on the standard +Column annotation, described in +. + + + + Datastore Identity Mapping + + +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; + + ... +} + + +
+
+ + Surrogate Version Mapping + + + + version + + + mapping + + + + + mapping metadata + + + version + + + version + + + + + VersionColumn + + + mapping metadata + + + +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 + +org.apache.openjpa.persistence.jdbc.VersionColumn +annotation. You can also use the + +org.apache.openjpa.persistence.jdbc.VersionColumns + annotation to declare an array of VersionColumn +values. Each VersionColumn has the following properties: + + + + +String name: Defaults to VERSN. + + + + +int length + + + + +int precision + + + + +int scale + + + + +String columnDefinition + + + + +boolean nullable + + + + +boolean insertable + + + + +boolean updatable + + + + +All properties correspond exactly to the same-named properties on the standard +Column annotation, described in +. + + +By default, OpenJPA assumes that surrogate versioning uses a version number +strategy. You can choose a different strategy with the +VersionStrategy annotation described in +. + +
+
+ + Multi-Column Mappings + + + + mapping metadata + + + column + + + + + mapping metadata + + + multi-column mappings + + + + + Columns + + + mapping metadata + + + +OpenJPA makes it easy to create multi-column +custom mappings. The JPA +specification includes a Column annotation, but is +missing a way to declare multiple columns for a single field. OpenJPA remedies +this with the + +org.apache.openjpa.persistence.jdbc.Columns +annotation, which contains an array of Column values. + + +Remember to annotate custom field types with Persistent, +as described in . + +
+
+ + Join Column Attribute Targets + + + in the JPA Overview introduced +you to the JoinColumn annotation. A +JoinColumn's referencedColumnName 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 +referencedColumnName that works for all subclasses. + + +OpenJPA rectifies this by allowing you to declare which attribute + 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 + +org.apache.openjpa.persistence.jdbc.XJoinColumn +annotation has all the same properties as the standard JoinColumn + annotation, but adds an additional +referencedAttributeName property for this purpose. Simply use a +XJoinColumn in place of a JoinColumn + whenever you need to access this added functionality. + + +For compound keys, use the + +org.apache.openjpa.persistence.jdbc.XJoinColumns +annotation. The value of this annotation is an array of individual +XJoinColumns. + +
+
+ + Embedded Mapping + + +JPA uses the AttributeOverride annotation to override the +default mappings of an embeddable class. The JPA Overview details this process +in . +AttributeOverrides 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. + + +OpenJPA overcomes these shortcomings with the + +org.apache.openjpa.persistence.jdbc.EmbeddedMapping + annotation. This annotation has the following properties: + + + + +String nullIndicatorColumnName: If the named column's value +is NULL, then the embedded object is assumed to be null. If +the named column has a non- NULL 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. + + +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 true to simply indicate that you +want a synthetic null-indicator column, without having to come up with a name +for it. A value of false signals that you explicitly do not +want a null-indicator column created for this mapping (in case you have +configured your mapping defaults + to create one by default). + + + + +String nullIndicatorFieldName: 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. + + + + +MappingOverride[] overrides: This array allows you to +override any mapping of the embedded object. + + + + +The EmbeddedMapping's overrides array +serves the same purpose as standard JPA's AttributeOverride +s and AssociationOverride s. In fact, you can +also use the MappingOverride annotation on an entity +class to override a complex mapping of its mapped superclass, just as you can +with AttributeOverride and +AssociationOverride s. The MappingOverrides +annotation, whose value is an array of MappingOverride s, +allows you to overide multiple mapped superclass mappings. + + +Each + +org.apache.openjpa.persistence.jdbc.MappingOverride + annotation has the following properties: + + + + +String name: The name of the field that is being overridden. + + + + +Column[] columns: Columns for the new field mapping. + + + + +XJoinColumn[] joinColumns: Join columns for the new field +mapping, if it is a relation field. + + + + +ContainerTable containerTable: Table for the new collection +or map field mapping. We cover collection mappings in +, and map mappings in +. + + + + +ElementJoinColumn[] elementJoinColumns: Element join columns +for the new collection or map field mapping. You will see how to use element +join columns in . + + + + +The following example defines an embeddable PathCoordinate + class with a custom mapping of a java.awt.Point + field to two columns. It then defines an entity which embeds a + PointCoordinate and overrides the default mapping for +the point field. The entity also declares that if the PathCoordinate +'s siteName field column is null, it means that +no PathCoordinate is stored in the embedded record; the +owning field will load as null. + + + + Overriding Complex Mappings + + +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; + + ... +} + + +
+
+ + Collections + + + + mapping metadata + + + collections + + + +In , we explored the +PersistentCollection annotation for persistent collection +fields that aren't a standard OneToMany or +ManyToMany relation. To map these non-standard collections, combine +OpenJPA's ContainerTable annotation with +ElementJoinColumns. +We explore the annotations below. + +
+ + Container Table + + + + ContainerTable + + + mapping metadata + + + +The + +org.apache.openjpa.persistence.jdbc.ContainerTable + annotation describes a database table that holds collection (or map) +elements. This annotation has the following properties: + + + + +String name + + + + +String catalog + + + + +String schema + + + + +XJoinColumn[] joinColumns + + + + +ForeignKey joinForeignKey + + + + +Index joinIndex + + + + +The name, catalog, schema +, and joinColumns 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 JoinTable +annotation, described in +. 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 joinForeignKey and joinIndex +properties override default foreign key and index generation for the join +columns. We explore foreign keys and indexes later in this chapter. + + +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. + +
+
+ + Element Join Columns + + + + ElementJoinColumn + + + mapping metadata + + + +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 + +org.apache.openjpa.persistence.jdbc.ElementJoinColumn + annotation. To declare a compound join, enclose an array of +ElementJoinColumns in the + +org.apache.openjpa.persistence.jdbc.ElementJoinColumns + annotation. + + +An ElementJoinColumn always resides in a container table, +so it does not have the table property of a standard + JoinColumn. Like XJoinColumns +above, ElementJoinColumns can reference a linked +attribute rather than a static linked column. Otherwise, the +ElementJoinColumn and standard JoinColumn +annotations are equivalent. See +in the JPA Overview for a review of the JoinColumn +annotation. + +
+
+ + Order Column + + + + OrderColumn + + + mapping metadata + + + +Relational databases do not guarantee that records are returned in insertion +order. If you want to make sure that your collection elements are loaded in the +same order they were in when last stored, you must declare an order column. +OpenJPA's + +org.apache.openjpa.persistence.jdbc.OrderColumn +annotation has the following properties: + + + + +String name: Defaults to ORDR. + + + + +boolean enabled + + + + +int precision + + + + +String columnDefinition + + + + +boolean insertable + + + + +boolean updatable + + + + +Order columns are always in the container table. You can explicitly turn off +ordering (if you have enabled it by default via your + mapping defaults) by setting +the enabled property to false. All other +properties correspond exactly to the same-named properties on the standard +Column annotation, described in +. + +
+
+
+ + One-Sided One-Many Mapping + + + + mapping metadata + + + collections + + + JPA one-sided one-many + + + +The previous section covered the use of ElementJoinColumn +annotations in conjunction with a ContainerTable for +mapping collections to dedicate tables. ElementJoinColumn +s, however, have one additional use: to create a one-sided one-many mapping. +Standard JPA supports OneToMany fields without a +mappedBy inverse, but only by mapping these fields to a +JoinTable (see + in the JPA Overview for +details). Often, you'd like to create a one-many association based on an inverse +foreign key (logical or actual) in the table of the related type. + + + + + + + + + +Consider the model above. Subscription has a collection +of LineItem s, but LineItem has +no inverse relation to Subscription. To retrieve all of +the LineItem records for a Subscription +, we join the SUB_ID inverse foreign key column +in the LINE_ITEM table to the primary key column of the +SUB table. The example below shows how to represent this +model in mapping annotations. Note that OpenJPA automatically assumes an inverse +foreign key mapping when element join columns are given, but no container or +join table is given. + + + + One-Sided One-Many Mapping + + +package org.mag.subscribe; + +import org.apache.openjpa.persistence.jdbc.*; + +@Entity +@Table(name="LINE_ITEM", schema="CNTRCT") +public class LineItem { + ... +} + +@Entity +@Table(name="SUB", schema="CNTRCT") +public class Subscription { + + @Id private long id; + + @OneToMany + @ElementJoinColumn(name="SUB_ID", target="ID") + private Collection<LineItem> items; + + ... +} + + +
+
+ + Maps + + + + mapping metadata + + + maps + + + +We detailed the ContainerTable annotation in +. Custom map mappings may +also use this annotation to represent a map table. + +
+
+ + Indexes and Constraints + + +OpenJPA uses index information during schema generation to index the proper +columns. OpenJPA uses foreign key and unique constraint information during +schema creation to generate the proper database constraints, and also at runtime +to order SQL statements to avoid constraint violations while maximizing SQL +batch size. + + +OpenJPA assumes certain columns have indexes or constraints based on your +mapping defaults, as detailed in . +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. + +
+ + Indexes + + + + mapping metadata + + + indexes + + + + + indexes + + + +The +org.apache.openjpa.persistence.jdbc.Index +annotation represents an index on the columns of a field. It is also used within +the ContainerTable + annotation to index join columns. +To index the columns of a collection element, use the + + org.apache.openjpa.persistence.jdbc.ElementIndex +annotation. These annotations have the following properties: + + + + +boolean enabled: Set this property to false + to explicitly tell OpenJPA not to index these columns, when OpenJPA +would otherwise do so. + + + + +String name: The name of the index. OpenJPA will choose a +name if you do not provide one. + + + + +boolean unique: Whether to create a unique index. Defaults +to false. + + + +
+
+ + Foreign Keys + + + + mapping metadata + + + foreign keys + + + + + foreign keys + + + +The +org.apache.openjpa.persistence.jdbc.ForeignKey +annotation represents a foreign key on the columns of a field. It is also used +within the +ContainerTable annotation to set a database foreign key on +join columns. To set a constraint to the columns of a collection element, use +the + + org.apache.openjpa.persistence.jdbc.ElementForeignKey + annotation. These annotations have the following properties: + + + + +boolean enabled: Set this property to false + to explicitly tell OpenJPA not to set a foreign key on these columns, +when OpenJPA would otherwise do so. + + + + +String name: The name of the foreign key. OpenJPA will +choose a name if you do not provide one, or will create an anonymous key. + + + + +boolean deferred: Whether to create a deferred key if +supported by the database. + + + + +ForeignKeyAction deleteAction: Value from the + +org.apache.openjpa.persistence.jdbc.ForeignKeyAction + enum identifying the desired delete action. Defaults to +RESTRICT. + + + + +ForeignKeyAction updateAction: Value from the + +org.apache.openjpa.persistence.jdbc.ForeignKeyAction + enum identifying the desired update action. Defaults to +RESTRICT. + + + + +Keep in mind that OpenJPA uses foreign key information at runtime to avoid +constraint violations; it is important, therefore, that your +mapping defaults and foreign +key annotations combine to accurately reflect your existing database +constraints, or that you configure OpenJPA to reflect on your database schema +to discover existing foreign keys (see +). + +
+
+ + Unique Constraints + + + + mapping metadata + + + unique constraints + + + + + unique constraints + + + +The +org.apache.openjpa.persistence.jdbc.Unique +annotation represents a unqiue constraint on the columns of a field. It is more +convenient than using the uniqueConstraints property of +standard JPA Table and SecondaryTable + annotations, because you can apply it directly to the constrained +field. The Unique annotation has the following +properties: + + + + +boolean enabled: Set this property to false + to explicitly tell OpenJPA not to constrain these columns, when +OpenJPA would otherwise do so. + + + + +String name: The name of the constraint. OpenJPA will choose +a name if you do not provide one, or will create an anonymous constraint. + + + + +boolean deferred: Whether to create a deferred constraint if +supported by the database. + + + +
+
+
+ + XML Column Mapping + + + + mapping metadata + + + xml column mapping + + + + + xml mapping column + + + +DB2, Oracle and SQLServer support XML column types and +XPath queries and indexes over these columns.OpenJPA supports mapping of an +entity property mapped to an XML column. + + +Annotate the entity property using the XMLValueHandler strategy: + + +@Persistent +@Strategy("org.apache.openjpa.jdbc.meta.strats.XMLValueHandler") + + +The default fetch type is EAGER but can be changed to LAZY by using: + + +@Persistence(fetch=FetchType.LAZY) + + +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 @XmlRootElement +appears in the root class. In some case this annotation needs to be added manually if it is missing. + + +The jaxb jar files must be on the application classpath (jaxb-api.jar, +jaxb-impl.jar, jsr173_1.0_api.jar or equivalent). + + +EJB Query path expressions can navigate into the mapped class and its +subfields to any level. + + +The path expression is rewritten into an equivalent XPATH expression using SQL +XML functions. + + +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 +(= <> < > >= <=). + + +Path expressions over XML mapped fields can not be: + + + + +an input to a EJB query scalar function + + + + +an operand of BETWEEN, IS NULL, LIKE or IN predicate + + + + +used to project out subfields in the SELECT clause + + + + +used in the FROM , GROUP BY, HAVING, ORDER BY clauses + + + + +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. + + +The datatype generated by JAXB must be a valid EJB query type +to use the property in an EJB query predicate. + + +Shown below is a sample XML schema myaddress.xsd, +in which the JPA entity Order has <shipAddress> persistent field that maps to an XML column. + + + + myaddress.xsd + + +<?xml version="1.0" ?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" > + +<xs:complexType name="Address"> + <xs:sequence> + <xs:element name="Name" type="xs:string" /> + <xs:element name="Street" type="xs:string" + minOccurs="1" maxOccurs="3" /> + <xs:element name="City" type="xs:string" /> +</xs:sequence> +</xs:complexType> + +<xs:complexType name="CAN_Address"> + <xs:complexContent> + <xs:extension base="Address"> + <xs:sequence> + <xs:element name="Province" type="xs:string" /> + <xs:element name="PostalCode" type="xs:string" /> + </xs:sequence> + </xs:extension> +</xs:complexContent> +</xs:complexType> + +<xs:simpleType name="USPS_ZIP"> + <xs:restriction base="xs:integer"> + <xs:minInclusive value="01000" /> + <xs:maxInclusive value="99999" /> + </xs:restriction> +</xs:simpleType> + +<xs:complexType name="USA_Address"> + <xs:complexContent> + <xs:extension base="Address"> + <xs:sequence> + <xs:element name="State" type="xs:string" /> + <xs:element name="ZIP" type="USPS_ZIP" /> + </xs:sequence> + </xs:extension> + </xs:complexContent> +</xs:complexType> + +<xs:element name="MailAddress" type="Address" /> +<xs:element name="AddrCAN" type="CAN_Address" + substitutionGroup="MailAddress" /> +<xs:element name="AddrUSA" type="USA_Address" + substitutionGroup="MailAddress" /> +</xs:schema> + + + +Java classes Address, +USAAddress and +CANAddress +are produced using jaxb XJC generator from myaddress schema. + + + + Address.Java + + + ... +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "Address", propOrder = { + "name", + "street", + "city" +}) +public class Address { + @XmlElement(name = "Name", required = true) + protected String name; + @XmlElement(name = "Street", required = true) + protected List<String> street; + @XmlElement(name = "City", required = true) + protected String city; + + /** + * Getter and Setter methods. + * + */ + ... +} + + + + + USAAddress.java + + + ... +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "USA_Address", propOrder = { + "state", + "zip" +}) +public class USAAddress + extends Address +{ + + @XmlElement(name = "State") + protected String state; + @XmlElement(name = "ZIP") + protected int zip; + + /** + * Getter and Setter methods. + * + */ + ... +} + + + + + CANAddress.java + + + ... +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CAN_Address", propOrder = { + "province", + "postalCode" +}) +public class CANAddress + extends Address +{ + + @XmlElement(name = "Province") + protected String province; + @XmlElement(name = "PostalCode") + protected String postalCode; + + /** + * Getter and Setter methods. + * + */ + ... +} + + + + + Showing annotated Order entity with XML mapping strategy + + +@Entity +public class Order { + @Id private into id; + @Persistent + @Strategy ("org.apache.openjpa.jdbc.meta.strats.XMLValueHandler") + private Address shipAddress; + ... +} + + + + + Showing creation of Order Entity having shipAddress mapped to XML column + + +... +myaddress.ObjectFactory addressFactory = new myaddress.ObjectFactory(); +Customer c1 = new Customer(); +c1.setCid( new Customer.CustomerKey("USA", 1) ); +c1.setName("Harry's Auto"); +Order o1 = new Order( 850, false, c1); +USAAddress addr1 = addressFactory.createUSAAddress(); +addr1.setCity("San Jose"); +addr1.setState("CA"); +addr1.setZIP(new Integer("95141")); +addr1.getStreet().add("12500 Monterey"); +addr1.setName( c1.getName()); +o1.setShipAddress(addr1); +em.persist(o1); +... + + + + + Sample EJB Queries for XML Column mapping + + +. select o from Order o where o.shipAddress.city = "San Jose" or + o.shipAddress.city = "San Francisco" (OK) + +. select o.shipaAddress from Order o (OK) + +. select o.shipAddress.city from Order o (INVALID) + +. select o from Order o where o.shipAddress.street = "San Jose" (INVALID multi valued) + + +
+
+
+ + Mapping Limitations + + + + mapping metadata + + + limitations + + + +The following sections outline the limitations OpenJPA places on specific +mapping strategies. + +
+ + Table Per Class + + + + mapping metadata + + + limitations + + + table-per-class + + + +Table-per-class inheritance mapping has the following limitations: + + + + +You cannot traverse polymorphic relations to non-leaf classes in a +table-per-class inheritance hierarchy in queries. + + + + +You cannot map a one-sided polymorphic relation to a non-leaf class in a +table-per-class inheritance hierarchy using an inverse foreign key. + + + + +You cannot use an order column in a polymorphic relation to a non-leaf class in +a table-per-class inheritance hierarchy mapped with an inverse foreign key. + + + + +Table-per-class hierarchies impose limitations on eager fetching. See +. + + + + + +Non-polymorphic relations do not suffer from these limitations. You can declare +a non-polymorphic relation using the extensions described in +. + + +
+
+
+ + Mapping Extensions + + +Mapping extensions allow you to access OpenJPA-specific functionality from your +mappings. Note that all extensions below are specific to mappings. If you store +your mappings separately from your persistence metadata, these extensions must +be specified along with the mapping information, not the persistence metadata +information. + +
+ + Class Extensions + + +OpenJPA recognizes the following class extensions. + +
+ + Subclass Fetch Mode + + + + mapping metadata + + + extensions + + + subclass fetch mode + + + eager fetching + + + +This extension specifies how to eagerly fetch subclass state. It overrides the +global +openjpa.jdbc.SubclassFetchMode property. Set the JPA + +org.apache.openjpa.persistence.jdbc.SubclassFetchMode + annotation to a value from the + +org.apache.openjpa.persistence.jdbc.EagerFetchType + enum: JOIN, PARALLEL, or +NONE. See + for a discussion of eager fetching. + +
+
+ + Strategy + + + + mapping metadata + + + extensions + + + strategy + + + custom mapping + + + +The +org.apache.openjpa.persistence.jdbc.Strategy +class annotation allows you to specify a custom mapping strategy for your class. +See for information on custom +mappings. + +
+
+ + Discriminator Strategy + + + + mapping metadata + + + extensions + + + discriminator strategy + + + custom mapping + + + +The + +org.apache.openjpa.persistence.jdbc.DiscriminatorStrategy + class annotation allows you to specify a custom discriminator strategy. +See for information on custom +mappings. + +
+
+ + Version Strategy + + + + mapping metadata + + + extensions + + + version strategy + + + custom mapping + + + +The + +org.apache.openjpa.persistence.jdbc.VersionStrategy + class annotation allows you to specify a custom version strategy. See + for information on custom +mappings. + +
+
+
+ + Field Extensions + + +OpenJPA recognizes the following field extensions. + +
+ + Eager Fetch Mode + + + + mapping metadata + + + extensions + + + eager fetch mode + + + eager fetching + + + +This extension specifies how to eagerly fetch related objects. It overrides the +global +openjpa.jdbc.EagerFetchMode property. Set the JPA + +org.apache.openjpa.persistence.jdbc.EagerFetchMode + annotation to a value from the + +org.apache.openjpa.persistence.jdbc.EagerFetchType + enum: JOIN, PARALLEL, or +NONE. See + for a discussion of eager fetching. + +
+
+ + Nonpolymorphic + + + + mapping metadata + + + extensions + + + nonpolymorphic + + + +All fields in Java are polymorphic. If you declare a field of type T +, you can assign any subclass of T to the field as +well. This is very convenient, but can make relation traversal very inefficient +under some inheritance strategies. It can even make querying across the field +impossible. Often, you know that certain fields do not need to be entirely +polymorphic. By telling OpenJPA about such fields, you can improve the +efficiency of your relations. + + + +OpenJPA also includes the type metadata extension for +narrowing the declared type of a field. See . + + + +OpenJPA defines the following extensions for nonpolymorphic values: + + + + + +org.apache.openjpa.persistence.jdbc.Nonpolymorphic + + + + + + +org.apache.openjpa.persistence.jdbc.ElementNonpolymorphic + + + + + +The value of these extensions is a constant from the + +org.apache.openjpa.persistence.jdbc.NonpolymorphicType + enumeration. The default value, EXACT, indicates +that the relation will always be of the exact declared type. A value of +JOINABLE, on the other hand, means that the relation might +be to any joinable subclass of the declared type. This value only excludes +table-per-class subclasses. + +
+
+ + Class Criteria + + + + mapping metadata + + + extensions + + + class criteria + + + joins + + + + + joins + + + class criteria + + + +This family of boolean extensions determines whether OpenJPA will use the +expected class of related objects as criteria in the SQL it issues to load a +relation field. Typically, this is not needed. The foreign key values uniquely +identify the record for the related object. Under some rare mappings, however, +you may need to consider both foreign key values and the expected class of the +related object - for example, if you have an inverse relation that shares the +foreign key with another inverse relation to an object of a different subclass. +In these cases, set the proper class critera extension to true + to force OpenJPA to append class criteria to its select SQL. + + +OpenJPA defines the following class criteria annotations for field relations and +array or collection element relations, respectively: + + + + + +org.apache.openjpa.persistence.jdbc.ClassCriteria + + + + + +org.apache.openjpa.persistence.jdbc.ElementClassCriteria + + + + +
+
+ + Strategy + + + + mapping metadata + + + extensions + + + strategy + + + custom mapping + + + +OpenJPA's + +org.apache.openjpa.persistence.jdbc.Strategy +extension allows you to specify a custom mapping +strategy or value handler for a field. See + for information on custom +mappings. + +
+
+
+
+ + Custom Mappings + + + + custom mapping + + + + + mapping metadata + + + custom mapping + + + custom mapping + + + +In OpenJPA, you are not limited to the set of standard mappings defined by the +specification. OpenJPA allows you to define custom class, discriminator, +version, and field mapping strategies with all the power of OpenJPA's built-in +strategies. + +
+ + Custom Class Mapping + + +To create a custom class mapping, write an implementation of the + +org.apache.openjpa.jdbc.meta.ClassStrategy +interface. You will probably want to extend one of the existing abstract or +concrete strategies in the org.apache.openjpa.jdbc.meta.strats + package. + + +The +org.apache.openjpa.persistence.jdbc.Strategy +annotation allows you to declare a custom class mapping strategy in JPA mapping +metadata. Set the value of the annotation to the full class name of your custom +strategy. You can configure your strategy class' bean properties using +OpenJPA's plugin syntax, detailed in . + +
+
+ + Custom Discriminator and Version Strategies + + +To define a custom discriminator or version strategy, implement the + +org.apache.openjpa.jdbc.meta.DiscriminatorStrategy + or + +org.apache.openjpa.jdbc.meta.VersionStrategy +interface, respectively. You might extend one of the existing abstract or +concrete strategies in the org.apache.openjpa.jdbc.meta.strats + package. + + +OpenJPA includes the + +org.apache.openjpa.persistence.jdbc.DiscriminatorStrategy + and + +org.apache.openjpa.persistence.jdbc.VersionStrategy + class annotations for declaring a custom discriminator or version +strategy in JPA mapping metadata. Set the string value of these annotations to +the full class name of your implementation, or to the class name or alias of an +existing OpenJPA implementation. + + +As with custom class mappings, you can configure your strategy class' bean +properties using OpenJPA's plugin syntax, detailed in +. + +
+
+ + Custom Field Mapping + + + + custom mapping + + + field mapping + + + +While custom class, discriminator, and version mapping can be useful, custom +field mappings are far more common. OpenJPA offers two types of custom field +mappings: value handlers, and full custom field strategies. The following +sections examine each. + +
+ + Value Handlers + + + + custom mapping + + + field mapping + + + value handler + + + +Value handlers make it trivial to map any type that you can break down into one +or more simple values. All value handlers implement the +org.apache.openjpa.jdbc.meta.ValueHandler interface; see its + Javadoc + for details. Also, examine the built-in handlers in the +src/openjpa/jdbc/meta/strats directory of your OpenJPA source +distribution. Use these functional implementations as examples when you +create your own value handlers. + +
+
+ + Field Strategies + + + + custom mapping + + + field mapping + + + field strategy + + + +OpenJPA interacts with persistent fields through the + +org.apache.openjpa.jdbc.meta.FieldStrategy interface. You +can implement this interface yourself to create a custom field strategy, or +extend one of the existing abstract or concrete strategies in the +org.apache.openjpa.jdbc.meta.strats package. Creating a custom field +strategy is more difficult than writing a custom value handler, but gives you +more freedom in how you interact with the database. + +
+
+ + Configuration + + + + custom mapping + + + field mapping + + + configuration + + + +OpenJPA gives you two ways to configure your custom field mappings. The +FieldStrategies property of the built-in +MappingDefaults 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. + described mapping +defaults in detail. + + +Your other option is to explicitly install a custom value handler or strategy on +a particular field. To do so, specify the full name of your implementation class +in the proper mapping metadata extension. OpenJPA includes the + +org.apache.openjpa.persistence.jdbc.Strategy +annotation. You can configure the named strategy or handler's bean +properties in these extensions using OpenJPA's plugin format (see +). + +
+
+
+
+ + Orphaned Keys + + +Unless you apply database foreign key constraints extensively, it is possible to +end up with orphaned keys in your database. For example, suppose +Magazinem has a reference to Article +a. If you delete a without +nulling m's reference, m's database +record will wind up with an orphaned key to the non-existent a + record. + + + +One way of avoiding orphaned keys is to use dependent +fields. + + + +OpenJPA's +openjpa.OrphanedKeyAction configuration property controls what +action to take when OpenJPA encounters an orphaned key. You can set this plugin +string (see ) to a custom +implementation of the + + org.apache.openjpa.event.OrphanedKeyAction +interface, or use one of the built-in options: + + + + +log: This is the default setting. This option logs a message +for each orphaned key. It is an alias for the + +org.apache.openjpa.event.LogOrphanedKeyAction +class, which has the following additional properties: + + + + +Channel: The channel to log to. Defaults to +openjpa.Runtime. + + + + +Level: The level to log at. Defaults to WARN +. + + + + + + +exception: Throw an +EntityNotFoundException when OpenJPA discovers an +orphaned key. This is an alias for the + +org.apache.openjpa.event.ExceptionOrphanedKeyAction + class. + + + + +none: Ignore orphaned keys. This is an alias for the + +org.apache.openjpa.event.NoneOrphanedKeyAction +class. + + + + + + Custom Logging Orphaned Keys + + +<property name="openjpa.OrphanedKeyAction" value="log(Channel=Orphans, Level=DEBUG)"/> + + +
+