5.4 Mapping Classes to Tables

If your object model does not use inheritance, you usually have a separate relational table for each class. We cover the mapping of classes in an inheritance hierarchy later in this chapter. To establish a mapping from a Java class to a specific table, in most JDO implementations you specify the mapping in your JDO metadata with an extension element nested within the class element. For example, the following example illustrates the metadata necessary to map the MediaItem class to a table called Items:

<class name="MediaItem" >
    <field name="rentalItems">
        <collection 
element-type="RentalItem"/>
    </field>
    <extension 
vendor-name="vendorX" key="table" value="Items" />
    <extension vendor-name="vendorY" key="sqlname" value="Items" />
</class>

You identify the implementation you are using in the vendor-name attribute. As we mentioned previously, the datastore mappings in JDO 1.0.1 are implementation-specific. This may be standardized in JDO 2.0. Each JDO vendor provides documentation explaining which value to use for the vendor-name attribute and which values are supported for the key attribute.

In the previous code, we provided the metadata for two vendors, identified as vendorX and vendorY. An implementation will use only metadata extensions that it recognizes. This allows you to place the metadata for multiple vendors in the same JDO metadata file. vendorX uses a value of "table" for the key attribute to indicate which relational table the MediaItem class should be mapped to, and vendorY uses the value "sqlname". You should check the implementation's documentation to see which values they require. We provide the name of the table (Items) in the relational schema in the value attribute. If you were to port your application to another JDO implementation, you would need to add an extension element that has values in the vendor-name and key attributes that are appropriate for that implementation. However, your Java class would not have to change.

If you don't specify a table for a class, most implementations assume that you would like them to generate the table name for you. You may or may not like the name that they use. If you are just prototyping your application and do not have an existing schema to map to, it can be more productive to just let the implementation generate any name. Once you move beyond the prototype stage of your project, you can always add this metadata to specify a specific name for the table.

You may wish to partition the fields of your class across multiple tables. Not all relational JDO implementations support this capability. To partition the fields of a class among several tables, you need to specify which table (and column) each field should be mapped to. An extension that is similar, or identical, to the one provided earlier would be placed in the field element instead of the class element.

If you use optimistic transactions, the JDO implementation requires either a version-number column or a list of columns whose values are used to detect concurrency violations. These track whether another transaction has performed a concurrent update on an instance. Another approach is to have a timestamp field that is updated whenever a row changes. Chapter 15 covers optimistic transactions and how they are implemented. Most implementations allow you to specify the name of the version column. If you don't specify the column name, the implementation uses a default column name.