2.3. Reverse Mapping Tool Tutorial
Prev | Chapter 2. JDO Tutorials | Next

## 2.3. Reverse Mapping Tool Tutorial

In this tutorial you will learn how to use Kodo's reverse mapping tool to reverse-engineer persistent classes from a database schema.

### 2.3.1. Magazine Shop

You run a shop that sells magazines. You store information about your inventory in a relational database with the following schema:

    -- Holds information on available magazines
    CREATE TABLE MAGAZINE (
        ISBN VARCHAR(8) NOT NULL,
        ISSUE INTEGER NOT NULL,
        NAME VARCHAR(255),
        PUBLISHER_NAME VARCHAR(255)
        PRICE FLOAT NOT NULL,
        PRIMARY KEY (ISBN, ISSUE)
        FOREIGN KEY (PUBLISHER_NAME) REFERENCES PUBLISHER (NAME)
    );

    -- Holds information on magazine articles
    CREATE TABLE ARTICLE (
        TITLE VARCHAR(255) NOT NULL,
        AUTHOR_NAME VARCHAR(128),
        PRIMARY KEY (TITLE)
    );

    -- Join table linking magazines and articles
    CREATE TABLE MAGAZINE_ARTICLES (
        MAGAZINE_ISBN VARCHAR(8),
        MAGAZINE_ISSUE INTEGER,
        ARTICLE_TITLE VARCHAR(255),
        FOREIGN KEY (MAGAZINE_ISBN, MAGAZINE_ISSUE) REFERENCES MAGAZINE (ISBN, ISSUE),
        FOREIGN KEY (ARTICLE_TITLE) REFERENCES ARTICLE (TITLE)
    );

    -- Each magazine has a 1-1 relation to its publisher
    CREATE TABLE PUBLISHER (
        NAME VARCHAR(255) NOT NULL,
        REVENUE FLOAT NOT NULL,
        PRIMARY KEY (NAME)
    );

You've decided to write an application that will let you query your database through JDO.

### 2.3.2. Setup

If you haven't already, follow the instructions in README.txt. This will ensure that your `CLASSPATH` and other environmental variables are set up correctly. Once you've completed the installation instructions, change into the `reversetutorial/jdo` directory.

#### 2.3.2.1. Tutorial Files

The tutorial uses the following files:

- `reversetutorial_database.properties` and `reversetutorial_database.script`: These files make up a Hypersonic file-based database with the schema outlined above. The database is already populated with lots of magazine data representing your shop's inventory.

- `reversetutorial.jdo.Finder`: Uses JDO to execute user-supplied query strings and output the matching persistent objects. This class relies on persistent classes that we haven't generated yet, so it won't compile immediately.

- `../../META-INF/jdo.properties`: Properties file containing Kodo-specific and standard JDO configuration settings.

  For this tutorial, make sure the following properties are set to the values below:

      javax.jdo.option.ConnectionURL: jdbc:hsqldb:reversetutorial_database
      javax.jdo.option.ConnectionDriverName: org.hsqldb.jdbcDriver
      javax.jdo.option.ConnectionUserName: sa
      javax.jdo.option.ConnectionPassword:

  | Important
  You must ensure you have valid BEA license key available to Kodo. For further details on Kodo licensing, see Section 2.2, “License Configuration”.

- `solutions`: Contains the complete solutions to this tutorial, including all generated code.

#### 2.3.2.2. Important Utilities

- `java`: Runs main methods in specified Java classes.

- `javac`: Compiles `.java` files into `.class` files that can be executed by `java`.

- `kodoc`: Runs the Kodo enhancer against the specified classes. More information is available in Section 5.2, “Enhancement” of the Reference Guide.

### 2.3.3. Generating Persistent Classes

Now it's time to turn your magazine database into persistent JDO classes mapped to each existing table. To accomplish this, we'll use Kodo's reverse mapping tools.

1. First, make sure that you are in the `reversetutorial/jdo` directory and that you've made the appropriate modifications to your `jdo.properties` file, as described in the previous section.

2. Now that we have our environment set up correctly, we're going to dump our existing schema to an XML document. This step is not strictly necessary for Hypersonic SQL, which provides good database metadata. Some databases, however, have faulty JDBC drivers, and Kodo is unable to gather enough information about the existing schema to create a good object model from it. In these cases, it is useful to dump the schema to XML, then modify the XML by hand to correct any errors introduced by the JDBC driver. If your schema doesn't use foreign key constraints, you may also want to add logical foreign keys to the XML file so that Kodo can create the corresponding relations between the persistent classes it generates.

   To perform the schema-to-XML conversion, we're going to use the schema tool, which can be invoked via the included `schematool` shell script. The `-p` option points the tool at your `jdo.properties` configuration file. `-a` denotes the tool's action. Finally, the `-f` flag tells the tool what to name the XML file it creates:

       schematool -p jdo.properties -a reflect -f schema.xml

   The schema tool is described in detail in Section 4.14, “Schema Tool” of the Reference Guide.

   | Note
   All Kodo JDO tools look for default configuration in a resource called `kodo.properties` or `META-INF/kodo.properties`. Thus you can avoid passing the `-p` argument to tools by using this configuration file name in place of `jdo.properties`. See Chapter 2, Configuration in the Reference Guide for details on Kodo configuration.

3. Examine the `schema.xml` XML file created by the schema tool. As you can see, it contains a complete representation of the schema for your magazine database. For the curious, this XML format is documented in Section 4.15, “XML Schema Format” of the Reference Guide.

4. Typically, JDO stores persistence and mapping metadata together in the same file. As shop owner, you've decided that you want to keep your mapping metadata separate from your persistence metadata. JDO supports separating object-relational mapping from persistence metadata through the `javax.jdo.option.Mapping` property. This property sets a logical name for your mappings. When it is set, JDO looks for mapping metadata in special mapping files suffixed with this name. Using the `javax.jdo.option.Mapping` property, you can separate concerns and even define multiple mappings for the same classes. You have chosen `hsql` as the logical name for your mappings to the supplied HSQL database. Add the following line to the `../../META-INF/jdo.properties` file:

       javax.jdo.option.Mapping: hsql

5. Run the reverse mapping tool on the schema file. (If you do not supply the schema file to reverse map, the tool will run directly against the schema in the database). The tool can be run via the included `reversemappingtool` script. Use the `-pkg` flag to control the package name of the generated classes.

       reversemappingtool -p jdo.properties -pkg reversetutorial.jdo schema.xml

   The reverse mapping tool has many options and customization hooks. For a complete treatment of the tool, see Section 7.2, “Reverse Mapping” of the Reference Guide.

   Running the reverse mapping tool will generate `.java` files for each generated class, `.java` files for corresponding JDO application identity classes, a `package.jdo` file containing persistence metadata, and a `package-hsql.orm` file containing object-relational mapping metadata. Chapter 5, Metadata and Chapter 15, Mapping Metadata of the JDO Overview discuss JDO persistence and mapping metadata, respectively.

6. Examine the generated persistent classes. Notice that the reverse mapping tool has used column and foreign key data to create the appropriate persistent fields and relations between classes. Notice, too, that due to the transparency of JDO, the generated code is vanilla Java, with no trace of JDO-specific functionality.

   Also examine `MagazineId`, the generated application identity class for `Magazine`. Note that it satisfies all of the requirements for application identity classes mandated by the JDO specification, including the `equals` and `hashCode` contracts. The other generated classes use JDO's single field identity, a special case of application identity for classes with only one primary key field. Section 4.5, “JDO Identity” explains JDO identity types.

   Finally, examine the `package.jdo` metadata file and `package-hsql.orm` mapping file. The former contains the necessary standard persistence metadata, while the latter maps the generated classes and their fields to the existing schema.

7. Compile the generated classes:

       javac *.java

The reverse mapping tool has now created a complete JDO object model for your magazine shop's existing relational model. From now on, you can treat the generated classes just like any other JDO class. And that means you have to complete one additional step before you can use the classes for persistence: enhancement.

    kodoc -p jdo.properties package.jdo

This step runs the Kodo JDO enhancer on the `package.jdo` file mentioned above. The Kodo enhancer will examine the file's metadata and enhance all listed classes appropriately. See Section 5.2, “Enhancement” in the Reference Guide for more information on the enhancer, including how to use Kodo's automatic runtime enhancement.

Congratulations! You are now ready to use JDO to access your magazine data.

### 2.3.4. Using the Finder

The `reversetutorial.jdo.Finder` class lets you run queries in JDOQL (JDO's Java-centric query syntax) against the existing database:

    java reversetutorial.jdo.Finder <jdoql-query>

JDOQL is discussed in Chapter 11, Query of the JDO Overview. JDOQL looks exactly like Java boolean expressions. To find magazines matching a set of criteria in JDOQL, just specify conditions on the `reversetutorial.jdo.Magazine` class' persistent fields. Some examples of valid JDOQL queries for magazines include:

    java reversetutorial.jdo.Finder "true"  // use this to list all the magazines
    java reversetutorial.jdo.Finder "price < 5.0"
    java reversetutorial.jdo.Finder "name == 'Vogue' || issue > 1000"
    java reversetutorial.jdo.Finder "name.startsWith('V')"

To traverse object relations, just use Java's dot syntax:

    java reversetutorial.jdo.Finder "publisher.name == 'Adventure' || publisher.revenue > 1000000"

To traverse collection relations, you have to use JDOQL variables. Variables are just placeholders for any member of a collection. For example, in the following query, `art` is a variable:

    java reversetutorial.jdo.Finder "articles.contains(art) && art.title.startsWith('JDO')"

The above query is equivalent to "find all magazines that have an article whose title starts with 'JDO'". For example, to find all magazines whose publisher published an article about "Next Gen" in any of its magazines:

    java reversetutorial.jdo.Finder "publisher.magazines.contains(mag) && mag.articles.contains(art) && art.title.startsWith('Next Gen')"

Have fun experimenting with additional queries.

| Note
Remember to erase the `javax.jdo.option.Mapping` setting in `../../META-INF/jdo.properties` before continuing with your own JDO experimentation, unless you'd like to continue to store your mapping information in separate mapping files rather than your `.jdo` metadata files.

Prev | Up | Next
2.2. Kodo JDO Tutorial | Home | 2.4. J2EE Tutorial