2.3. Reverse Mapping Tool Tutorial

2.3.1. Magazine Shop
2.3.2. Setup
2.3.2.1. Tutorial Files
2.3.2.2. Important Utilities
2.3.3. Generating Persistent Classes
2.3.4. Using the Finder

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: 
    

  • 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]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]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.

 

Skip navigation bar   Back to Top