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.
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.
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 | build | retain | none>: The action to take on the schema. These options correspond to the same-named actions on the schema tool described in Section 8.2, “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 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 data store. 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 data store. 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.
-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 Kodo 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 very 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 unless the readSchema flag is set to true.
-foreignKeys/-fk <true/t | false/f>: Whether to read and manipulate foreign key information of existing tables. Defaults to false unless the readSchema flag is set to true. This means that if you add a jdbc-delete-action extension to a field of a class that has already been mapped once, you must explicitly set this flag to true to have Kodo create the new foreign key on the existing table.
-indexes/-ix <true/t | false/f>: Whether to read and manipulate index information of existing tables. Defaults to false unless the readSchema flag is set to true. This means that if you add a jdbc-indexed extension to a field of a class that has already been mapped once, you must explicitly set this flag to true to have Kodo create the new index on the existing table.
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 in Section 7.4, “Mapping File XML Format”.
export: Export the mapping data for the given classes to an XML file. The XML format used for mapping data is discussed in Section 7.4, “Mapping File XML Format”.
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.
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.
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.
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.
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.
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.
The buildSchema action is also useful if you would like Kodo to do most of your mappings, but you want to edit a few of the mappings or table/column names Kodo generates:
Example 7.6. Modifying Default Mappings
First, run the mapping tool with a none schema action to generate default mappings without changing the database:
mappingtool -a refresh -sa none package.jdo
Next, modify the default mappings to fit your needs. You only have to do this once; Kodo will continue to use the modified mappings as long as they remain valid. Finally, build the schema based on your mappings:
mappingtool -a buildSchema package.jdo
Finally, some mapping factories allow you to revert mapping data if they have saved a copy.
Sometimes you do not want Kodo to make the changes to your database, but rather you want to have a script of the SQL that Kodo would use. The examples below show how to use the mapping tool to generate DDL SQL scripts.
Example 7.8. Refresh Mappings and Create DDL
This example refreshes the mappings for the classes in package.jdo and writes all the SQL necessary to create the tables used by these mappings to create.sql.
mappingtool -a refresh -sa build -sql create.sql package.jdo
Example 7.9. Refresh Mappings and Create DDL to Update Database
This example refreshes the mappings for the classes in package.jdo. It writes the SQL to add tables or columns missing from the current schema to the update.sql file.
mappingtool -a refresh -sql update.sql package.jdo
Example 7.10. 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.
mappingtool -a buildSchema -sa build -sql create.sql package.jdo