Chapter 7. Object-Relational Mapping

7.1. Mapping Tool
7.1.1. Using the Mapping Tool
7.2. Mapping Factory
7.2.1. Importing and Exporting Mapping Data
7.3. Mapping File XML Format
7.4. Mapping Notes
7.4.1. Join Attributes
7.4.2. Non-Standard Joins
7.5. Class Mapping
7.5.1. Base Mapping
7.5.2. Flat Mapping
7.5.3. Vertical Mapping
7.5.4. Custom Class Mapping
7.6. Version Indicator
7.6.1. Version Number Indicator
7.6.2. Version Date Indicator
7.6.3. State Image Indicator
7.6.4. Custom Version Indicator
7.7. Class Indicator
7.7.1. In-Class-Name Indicator
7.7.2. Metadata Value Indicator
7.7.3. Custom Class Indicator
7.8. Field Mapping
7.8.1. Value Mapping
7.8.2. Blob Mapping
7.8.3. Clob Mapping
7.8.4. Stringification Mapping
7.8.5. One-to-One Mapping
7.8.6. PC One-to-One Mapping
7.8.7. Embedded One-to-One Mapping
7.8.8. Collection Mapping
7.8.9. Many-to-Many Mapping
7.8.10. One-to-Many Mapping
7.8.11. PC Collection Mapping
7.8.12. Map Mapping
7.8.13. N-to-Many Map Mapping
7.8.14. Many-to-N Map Mapping
7.8.15. Many-to-Many Map Mapping
7.8.16. PC Map Mapping
7.8.17. N-to-PC Map Mapping
7.8.18. PC-to-N Map Mapping
7.8.19. PC-to-Many Map Mapping
7.8.20. Many-to-PC Map Mapping
7.8.21. Custom Field Mapping

Object-relational mapping is the process of mapping software objects to relational database tables. Kodo JDO has a full-featured mapping system including built-in support for most object-oriented patterns and schema designs. You are not limited to what Kodo JDO bundles by default, however. Kodo JDO's mapping system is designed with flexibility and extensibility in mind, so you can easily create custom mappings to meet your exact needs. This chapter reviews the mapping utilities Kodo JDO provides, the built-in mappings it supports, and how to create your own mappings should the need arise.

7.1. Mapping Tool

Kodo JDO allows you to control the mapping process yourself, but it also provides tools to automate mapping. We already saw one example of Kodo JDO's object-relational mapping tools when we discussed the reverse mapping tool. In this section, we discuss another mapping utility, simply called the mapping tool. While the reverse mapping tool creates classes and mapping data from an existing schema, the mapping tool creates the schema and mapping data from existing classes. The mapping tool can also be used to validate mapping data that you've written yourself, or to import and export mapping data to and from the current mapping factory.

We describe common mapping tool use cases in the next section. You can invoke the mapping tool through the mappingtool shell/batch script included in the Kodo JDO distribution, or through its Java class, kodo.jdbc.meta.MappingTool.

Example 7.1. Using the Mapping Tool

mappingtool -a refresh *.jdo

In addition to the universal flags of the configuration framework, the mapping tool accepts the following command line arguments:

  • -file/-f <stdout | output file>: Use this option to write the planned mappings to an XML document rather than recording them as the mappings for the given classes. This option also specifies the file to dump to if using the export tool action.

  • -schemaAction/-sa <add | refresh | retain | none> : The action to take on the schema. These options correspond to the same-named actions on the schema tool. Unless you are running the mapping tool on all of your persistent types at once, we strongly recommend you use the default add schema 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 data store. The document can then be manipulated and committed to the database with the schema tool.

  • -dropTables/-dt <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 set to false.

  • -readSchema/-rs <true/t | false/f>: Set this option to false to prevent reading of the entire existing schema when the tool runs. The parts of the schema used by the classes the tool is run on will still be read. Turning off schema reading can improve performance of the tool for large schemas, but is also dangerous if you are using this tool to create new mappings. The tool will not be able to detect what table and index names are already taken by existing schema components, and may generate mappings that cause conflicts.

The mapping tool requires an -action/-a argument specifying the action to take on each class. The available actions are:

  • refresh: Bring the mapping information up-to-date with the class definitions. Classes or fields whose mappings no longer match the class definition or schema will be re-mapped to new columns/tables.

  • drop: Remove the mapping information for the given classes.

  • validate: Validate that the mappings for the given classes are valid and that they match the schema. No mappings or tables will be changed; an exception will be thrown if any mappings are invalid.

  • buildSchema: Create the schema based on the existing mappings for the given classes.

  • revert: Revert the mappings for the given classes to their previously saved state. Some mapping factories may not be able to revert mapping data.

  • import: Import mapping information from the given XML document and add it to the stored system mappings. The XML format used for mapping data is discussed here.

  • export: Export the mapping data for the given classes to an XML file. The XML format used for mapping data is discussed here.

Each additional argument to the tool should be either the full name of a persistent class, the .java file of a persistent class, the .class file of a persistent class, or a .jdo metadata file listing one or more persistent classes to act on. If the import action is used, however, then any additional arguments will be interpreted as XML mapping data files.

The mapping data generated by the mapping tool is stored in the system mapping factory. As you will see later in this chapter, you have several mapping factories to choose from. Thus, mapping data might end up stored in the database, in special mapping files, in JDO metadata vendor extensions, or in another format of your choosing.

7.1.1. Using the Mapping Tool

There are three primary approaches to object-relational mapping: object-to-schema, schema-to-object, and meet-in-the-middle. The mapping tool has actions to facilitate each approach.

In the object-to-schema approach to mapping, you concentrate your efforts on your object model, and the mapping tool's refresh action keeps your mappings and schema up-to-date. The refresh action examines both the existing database schema and any existing mapping information. Classes and fields that are not mapped, or whose mapping information no longer matches the object model or the schema, are automatically given new mappings. The tool also updates the schema as necessary to support these new mappings. The example below shows how to invoke the refresh action on the mapping tool to create or update the mapping information and database schema for the persistent classes listed in package.jdo.

Example 7.2. Refreshing Mappings and the Relational Schema

mappingtool -a refresh package.jdo

You can safely run the refresh action on classes that have already been mapped, because the tool only generates new mappings when the old ones have become incompatible with the class or the schema. If the tool does have to replace a bad mapping, it does not modify other still-valid mappings. For example, if you change the type of a field from int to String, the mapping tool will detect the incompatibility with the old numeric column, add a new string-compatible column to the class' database table, and change the field's mapping data to point to the new column. All other fields will retain their original mappings.

In order to ensure that the table, column, and index names it generates for new mappings are unique, the mapping tool usually invokes the schema generator on startup. The schema generator reflects on the database schema to see what names are already taken. This can be a slow process for large schemas. There are two ways to speed things up:

  1. If you have multiple schemas, limit the schema generator to the schema(s) you are currently interested in. You can do this by specifying the -schemas <schema names> flag to the mapping tool. The given schema names string is comma-separated. The relevant schemas can also be configured on a global basis with the kodo.jdbc.Schemas configuration property.

  2. Turn off schema reading with the -readSchema false mapping tool flag. When you specify this flag, the mapping tool will only read the table definitions for the mappings it is currently working with; it will not attempt to gather information on the entire schema. Keep in mind that without knowledge of the entire schema, the mapping tool may try to create tables or indexes whose names clash with existing schema components. This flag is fairly safe to use, however, because the tool will still be able to detect column name conflicts, and Kodo JDO's table and index naming conventions are such that most table and index name conflicts will be avoided as well.

To drop mapping data, use the drop action. This action does not affect the schema. Dropping mapping data for unused classes is not strictly necessary, but it might slightly increase performance under some mapping factories.

Example 7.3. Dropping Mappings

mappingtool -a drop package.jdo

The second approach to object-relational mapping is the schema-to-object approach. We have already seen how to use the reverse mapping tool to generate persistent classes and mapping information from an existing schema. Once you complete the reverse mapping, you may want to tweak the output of the reverse mapping tool. At this point you have both an existing schema and existing mapping information (from the reverse mapping tool), and you are modifying both by hand. Thus, you are really using the final, meet-in-the-middle approach to 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, possibly with the aid of Kodo JDO's GUI tools. In this scenario, you will find the mapping tool's validate action useful. The validate action verifies that the mapping information for a class matches the class definition and the existing schema.

Example 7.4. Validating Mappings

mappingtool -a validate package.jdo

The buildSchema tool action is also useful for meet-in-the-middle mapping. Unlike the validate action, which throws an exception if the mapping data does not match the existing schema, or the refresh action, which replaces inconsistent mappings, 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.

Example 7.5. Updating the Schema Based on Mapping Data

mappingtool -a buildSchema package.jdo

Finally, some mapping factories allow you to revert mapping data if they have saved a copy.

Example 7.6. Reverting Mapping Data

mappingtool -a revert package.jdo