Chapter 5. Metadata
Prev | Part II. Java Data Objects | Next

## Chapter 5. Metadata

JDO requires that you accompany each persistence-capable class with JDO metadata. This metadata serves three primary purposes:

1. To identify persistence-capable classes.

2. To override default JDO behavior.

3. To provide the JDO implementation with information that it cannot glean from simply reflecting on the persistence-capable class.

Metadata is specified as a document in the eXtensible Markup Language (XML). The Document Type Definition (DTD) for metadata documents is given in the next section. Do not worry about digesting the entire DTD immediately; we will fully cover each aspect of metadata in turn.

## 5.1. Metadata DTD

    <!ELEMENT jdo (package)+>

    <!ELEMENT package ((class)+, (extension)*)>
    <!ATTLIST package name CDATA #REQUIRED>

    <!ELEMENT class (field|extension)*>
    <!ATTLIST class name CDATA #REQUIRED>
    <!ATTLIST class identity-type (application|datastore|none) 'datastore'>
    <!ATTLIST class objectid-class CDATA #IMPLIED>
    <!ATTLIST class requires-extent (true|false) 'true'>
    <!ATTLIST class persistence-capable-superclass CDATA #IMPLIED>

    <!ELEMENT field ((collection|map|array)?, (extension)*)>
    <!ATTLIST field name CDATA #REQUIRED>
    <!ATTLIST field persistence-modifier (persistent|transactional|none) 'persistent'>
    <!ATTLIST field primary-key (true|false) 'false'>
    <!ATTLIST field null-value (exception|default|none) 'none'>
    <!ATTLIST field default-fetch-group (true|false) #IMPLIED>
    <!ATTLIST field embedded (true|false) #IMPLIED>

    <!ELEMENT array (extension)*>
    <!ATTLIST array embedded-element (true|false) #IMPLIED>

    <!ELEMENT collection (extension)*>
    <!ATTLIST collection element-type CDATA #IMPLIED>
    <!ATTLIST collection embedded-element (true|false) #IMPLIED>

    <!ELEMENT map (extension)*>
    <!ATTLIST map key-type CDATA #IMPLIED>
    <!ATTLIST map embedded-key (true|false) #IMPLIED>
    <!ATTLIST map value-type CDATA #IMPLIED>
    <!ATTLIST map embedded-value (true|false) #IMPLIED>

    <!ELEMENT extension (extension)*>
    <!ATTLIST extension vendor-name CDATA #REQUIRED>
    <!ATTLIST extension key CDATA #IMPLIED>
    <!ATTLIST extension value CDATA #IMPLIED>

The root element of all metadata documents is the `jdo` element. The only legal children of the `jdo` element are `package` elements. Each `package` element must specify a `name` attribute giving the full name of the package it represents.

Example 5.1. Basic Structure of Metadata Documents

    <?xml version="1.0"?>
    <jdo>
        <package name="org.mag">
            ...
        </package>
        <package name="org.mag.subscribe">
            ...
        </package>
    </jdo>

`package` elements contain one or more `class` elements, followed by zero or more `extension` elements. Extensions are used to annotate metadata with vendor-specific information. The `extension` element may contain nested `extension` elements, and has three attributes:

- `vendor-name`: The name of the vendor the extension applies to. This attribute is required.

- `key`: The name of the property you are setting with the extension. Each vendor will supply a list of supported properties.

- `value`: The value of the property.

| Note
Kodo JDO defines many useful metadata extensions. See the Kodo JDO Reference Guide chapter on metadata extensions for a full list.

Every persistence-capable class in the package named by each `package` element must be represented by a `class` element. Before we explore this element in detail, a brief note on how JDO resolves class names is in order.

Several metadata attributes require you to specify class names. The names you give should follow these guidelines:

- If the class is in the package named by the current `package` element, you can give just the class name, without specifying the package. For example, if the current `package` name is `org.mag` and the class is `org.mag.Magazine`, then you can simply write `Magazine` for the class name.

- Similarly, if the class is in `java.lang`, `java.util`, or `java.math` packages, you do not need to specify the package in the class name.

- Otherwise, the full class name is required, including package name.

- If the class is an inner class, then write it as `parent-class$inner-class` For example, `SubscriptionForm$LineItem`.

We now turn our attention back to the `class` element. This element has the following attributes:

- `name`: The name of the class. This attribute is required.

- `persistence-capable-superclass`: If the superclass of this class is also persistent, and you wish JDO to know about the inheritance structure, then you must name the superclass in this attribute. If the superclass of this class is not persistent or if for some reason you want JDO to treat the superclass as unrelated, you should not specify this attribute.

- `identity-type`: Gives the JDO identity type used by the class. Legal values are `application` for application identity, `datastore` for datastore identity, and `none`. This attribute defaults to a value of `application` if the `objectid-class` attribute is specified, and `datastore` otherwise.

- `objectid-class`: For application identity, the name of the JDO identity class used by this class. The `objectid-class` should only be given for the base class in the inheritance tree; subclasses will "inherit" the identity class from their superclass.

  | Note
  As well as having a single application identity class for an entire inheritance tree, Kodo JDO also allows the definition of a separate application identity class for each level of the persistent inheritance hierarchy. The inheritance hierarchy of the application id classes must exactly match the inheritance hierarchy of the persistence capable classes that they represent. See Section 4.5.2.1, “Application Identity Hierarchies”.

- `requires-extent`: Set this attribute to `false` if you will never need to query for persistent instances of this class (i.e., if all objects of the class can be obtained through JDO identity lookups or through relations with other objects). Defaults to `true`.

Example 5.2. Metadata Class Listings

    <?xml version="1.0"?>
    <jdo>
        <package name="org.mag">
            <class name="Magazine" objectid-class="Magazine$ObjectId">
                ...
            </class>
            <class name="Article">
                ...
            </class>
            <class name="Author">
                ...
            </class>
            <class name="Address">
                ...
            </class>
        </package>
        <package name="org.mag.subscribe">
            <class name="Form">
                ...
            </class>
            <class name="SubscriptionForm" persistence-capable-superclass="Form">
                ...
            </class>
            <class name="SubscriptionForm$LineItem">
                ...
            </class>
        </package>
    </jdo>

The `class` element may contain `extension` elements and `field` elements. `field` elements represent fields declared by the persistence-capable class. These elements are optional; if a field declared in the class is not named by some `field` element, then its properties are defaulted as explained in the attribute listings below. Thanks to JDO's comprehensive set of defaults, most fields do not need to be listed explicitly. `field` elements may have the following attributes:

- `name`: The name of the field, as it is declared in the persistence-capable class. This attribute is required.

- `persistence-modifier`: Specifies how JDO should manage the field. Legal values are `persistent` for persistent fields, `transactional` for fields that are non-persistent but can be rolled back along with the current transaction, and `none`. The default value of this attribute is based on the type of the field:

  - Fields declared `static, transient`, or `final` default to `none`.

  - Fields of any primitive or primitive wrapper type default to `persistent`.

  - Fields of types `java.lang.String, java.lang.Number, java.math.BigDecimal, java.math.BigInteger, java.util.Locale`, and `java.util.Date` default to `persistent`.

  - Fields of any user-defined persistence-capable type default to `persistent`.

  - Arrays of any of the types mentioned so far default to `persistent`.

  - Fields of the following container types in the `java.util` package default to `persistent`: `Collection, Set, List, Map, ArrayList, HashMap, HashSet, Hashtable, LinkedList, TreeMap, TreeSet, Vector`.

  - All other fields default to `none`.

- `primary-key`: Set this attribute to `true` if the class uses application identity and this field is a primary key field. Defaults to `false`.

- `null-value`: Specifies the treatment of `null` values when the field is written to the data store. Use a value of `none` if the data store should hold a `null` value for the field. Use `default` to write a data store default value instead. Finally, use `exception` if you want the JDO implementation to throw an exception if the field contains a `null` value when it is being written to the data store. Defaults to `none`.

- `default-fetch-group`: Default fetch group fields are managed together as a group for efficiency. They are typically loaded as a block from the data store, and are often written as a block as well. This attribute defaults to `true` for primitive, primitive wrapper, `String, Date, BigDecimal`, and `BigInteger` types. All other types default to `false`.

  | Note
  Kodo JDO allows you to define multiple fetch groups. It also supports eager fetching of related objects when a fetch group is loaded for maximum performance.

- `embedded`: This is a hint to the JDO implementation to store the field as part of the class instance in the data store, rather than as a separate entity. JDO implementations are free to ignore this attribute. Its value defaults to `true` for primitive, primitive wrapper, `Date, BigDecimal, BigInteger`, array, collection, and map types. All other types default to `false`. Embedded objects do not appear in the `Extent` for their class, and cannot be retrieved by query.

| Note
When you mark a relation to another persistence-capable object as embedded, Kodo JDO stores the object in the same table row in the database as the parent object. Kodo even allows recursively embedded objects (a `Company` has an embedded `Address` which has an embedded `PhoneNumber`, for example).

All `field` elements may contain `extension` child elements. `field` elements that represent array, collection, or map fields may also contain a single `array`, `collection`, or `map` child element, respectively. Each of these elements may contain additional `extension` elements in turn.

The `array` element has a single attribute, `embedded-element`. This attribute mirrors the `embedded` attribute of the `class` element, but applies to the values stored in each array index.

The `collection` element also has the `embedded-element` attribute. Additionally, it declares the `element-type` attribute. Use this attribute to tell the JDO implementation what class of objects the collection contains. If the `element-type` is not given, it defaults to `java.lang.Object`.

`map` elements define four attributes. They are:

- `key-type`: The class of objects used for map keys. Defaults to `java.lang.Object`.

- `embedded-key`: Same as the `embedded-element` element of arrays and collections, but applies to map keys.

- `value-type`: The class of objects used for map values. Defaults to `java.lang.Object`.

- `embedded-value`: Same as the `embedded-element` element of arrays and collections, but applies to map values.

That exhausts the metadata document structure. A complete metadata document example is presented below.

Example 5.3. Complete Metadata Document

    <?xml version="1.0"?>
    <!-- Note that all persistence-capable classes must be listed, but -->
    <!-- very few fields need to be specified                          -->
    <jdo>
        <package name="org.mag">
            <class name="Magazine" objectid-class="Magazine$ObjectId">
                <field name="isbn" primary-key="true"/>
                <field name="title" primary-key="true"/>
                <field name="articles">
                    <collection element-type="Article"/>
                </field>
            </class>
            <class name="Article">
                <field name="authors">
                    <map key-type="String" value-type="Author"/>
                </field>
            </class>
            <class name="Author">
                <field name="address" embedded="true"/>
            </class>
            <class name="Address"/>
        </package>
        <package name="org.mag.subscribe">
            <class name="Form"/>
            <class name="SubscriptionForm" persistence-capable-superclass="Form">
                <field name="lineItems">
                    <collection element-type="SubscriptionForm$LineItem"/>
                    <extension vendor-name="kodo" key="inverse-owner" value="form"/>
                </field>
            </class>
            <class name="SubscriptionForm$LineItem"/>
        </package>
    </jdo>

Prev | Up | Next
4.6. Conclusions | Home | 5.2. Metadata Placement