7.9. Field Mapping
Prev | Chapter 7. Object-Relational Mapping | Next

## 7.9. Field Mapping

A field mapping describes how a persistent field maps to the database. If necessary, it also contains data on how to link the field to the data of its owning object, and how to link the field to the data of any related objects (if the field represents a relation to one or more other persistent objects).

In Kodo JDO, field mappings extend the base `kodo.jdbc.meta.FieldMapping` class. The concrete field mappings Kodo JDO provides are described in the sections below. By default, the mapping tool decides which field mapping to use for a particular field by cycling through all the known mappings until one returns `true` from its `map` method. You can instruct the mapping tool to use a specific mapping for an individual field with the `jdbc-field-map-name` JDO metadata extension.

This section concludes with a discussion of externalization in Section 7.9.23, “Externalization”, a Kodo feature that allows you to persist many field types that aren't supported directly by JDO without a custom field mapping, and without resorting to serialization.

### 7.9.1. Value Mapping

The value mapping represents the direct mapping of a Java primitive, primitive wrapper, Date, or string to a compatibly-typed database column. The value mapping has the following attributes:

- `type`: value

- `column`: The name of the column that stores the field value. This property is required.

- `table`: If the column is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the column is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equivalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

Example 7.27. Using a Value Mapping

    Java class:

    public class Magazine
    {
        private String isbn;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="ISBN" type="varchar" size="10"/>
        ... columns for magazine fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="isbn">
            <jdbc-field-map type="value" column="ISBN"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="isbn">
            <extension vendor-name="kodo" key="jdbc-field-map" value="value">
                <extension vendor-name="kodo" key="column" value="ISBN"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

Example 7.28. Using a Value Mapping in a Separate Table

Note that though we do not include separate-table examples for any other field mappings, all other built-in field mapping types can be used in a separate table, following the same pattern as the example below.

    Java class:

    public class Magazine
    {
        private String isbn;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="BIGINT"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_EXTRAS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ISBN" type="varchar" size="10"/>
        ... columns for other fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="isbn">
            <jdbc-field-map type="value" column="ISBN"
                table="MAG_EXTRAS" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="isbn">
            <extension vendor-name="kodo" key="jdbc-field-map" value="value">
                <extension vendor-name="kodo" key="column" value="ISBN"/>
                <extension vendor-name="kodo" key="table" value="MAG_EXTRAS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.2. Blob Mapping

The blob mapping serializes the value of the Java field it is installed on, and stores the serialized bytes in a binary database column. Fields whose type is unrecognized or `java.lang.Object`, collections and arrays whose `element-type` is unspecified, unrecognized, or set to `java.lang.Object`, maps whose `key-type, value-type`, or both is unspecified, unrecognized, or `java.lang.Object`, and non-string fields that have set the `jdbc-size` JDO metadata extension to -1 all default to using blob mappings. Also, see the `type` JDO metadata extension for how to force an interface-typed field to use a blob mapping.

The blob mapping has the following attributes:

- `type`: blob

- `column`: The name of the binary column that stores the field value. This property is required.

- `table`: If the column is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the column is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equievalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

Example 7.29. Using a Blob Mapping

    Java class:

    public class Magazine
    {
        private Object data;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="DATA" type="blob"/>
        ... columns for magazine fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="data" persistence-modifier="persistent"/>
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="data">
            <jdbc-field-map type="blob" column="DATA"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="data">
            <extension vendor-name="kodo" key="jdbc-field-map" value="blob">
                <extension vendor-name="kodo" key="column" value="DATA"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.3. Clob Mapping

The clob mapping is reserved for string fields that map to a database `CLOB` column. You can indicate that a string should be stored as a `CLOB` by setting the `jdbc-size` JDO metadata extension on the field to -1. Note that some databases can support string of unlimited length without using a `CLOB`; when this is the case the mapping tool will install a value mapping in favor of this mapping.

The clob mapping has the following attributes:

- `type`: clob

- `column`: The name of the `CLOB` column that stores the field value. This property is required.

- `table`: If the column is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the column is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equievalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

Example 7.30. Using a Clob Mapping

    Java class:

    public class Magazine
    {
        private String coverStorySummary;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="COVERSUMMARY" type="clob"/>
        ... columns for magazine fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="coverStorySummary">
            <extension vendor-name="kodo" key="jdbc-size" value="-1"/>
        </field>
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="coverStorySummary">
            <jdbc-field-map type="clob" column="COVERSUMMARY"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="coverStorySummary">
            <extension vendor-name="kodo" key="jdbc-size" value="-1"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="clob">
                <extension vendor-name="kodo" key="column" value="COVERSUMMARY"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.4. Byte Array Mapping

The byte array mapping is a mapping specifically for `byte` array fields. Unlike blob mapping, this mapping does not serialize or deserialize your byte array and instead stores the array directly to the database. This is useful for binary columns which are generated by legacy or non-Java applications.

The byte array mapping has the following attributes:

- `type`: byte-array

- `column`: The name of the binary column that stores the field value. This property is required.

- `table`: If the column is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the column is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equievalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

Example 7.31. Using a Byte array Mapping

    Java class:

    public class Magazine
    {
        private byte [] coverData;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="COVER_DATA" type="blob"/>
        ... columns for magazine fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="coverData">
            <jdbc-field-map type="byte-array" column="COVER_DATA"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="data">
            <extension vendor-name="kodo" key="jdbc-field-map" value="byte-array">
                <extension vendor-name="kodo" key="column" value="COVER_DATA"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.5. One-to-One Mapping

A one-to-one mapping represents a field that holds a reference to another persistent object. One-to-one mappings can be one-sided or two-sided. In the latter case, two objects hold a reference to each other, but only the database record for the "owner" of the relation holds the primary key values of the inverse object.

If your database defines a non-deferred foreign key constraint for the relation, you should be sure to set the kodo.jdbc.ForeignKeyConstraints property appropriately.

The one-to-one mapping has the following attributes:

- `type`: one-one

- `column.<pk column>`*: Kodo JDO must be able to join this mapping's columns to the row of the related object. Each `column` attribute joins a column in the local table to the corresponding column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `table`: If the join columns are not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the join columns are not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equievalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

- `class-criteria`: Whether or not to use the expected class of the related object as a criteria in the SQL issued to select its database record. Typically, this is not needed; Kodo can just use the foreign key value to select the desired record, and if your database data is valid, the record will correspond to an object of the correct class. Under some very rare mappings, however, you may need to select based on both foreign key and class -- for example, if you are using an inverse-based one-one relation that shares the inverse foreign key with another inverse-based one-one to an object of a different subclass. In these rare cases, set this attribute to `true` to force Kodo to append class conditions to its SQL.

Example 7.32. Using a One-to-One Mapping

    Java class:

    public class Magazine
    {
        private Headquarters hq;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="HQID" type="bigint"/>
        <fk to-table="HEADQUARTERS">
            <join column="HQID" to-column="ID"/>
        </fk>
        ... columns for magazine fields ...
    </table>

    <table name="HEADQUARTERS">
        <column name="ID" type="bigint"/>
        <pk column="ID"/>
        ... columns for headquarters fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="hq">
            <jdbc-field-map type="one-one" column.ID="HQID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="hq">
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-one">
                <extension vendor-name="kodo" key="column.ID" value="HQID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

Example 7.33. Using a Two-Sided One-to-One Mapping

This example is the same as the previous one, except that now the `Headquarters` class includes an inverse relation to `Magazine`. The `MAGAZINE` table columns for the `hq` field control both sides of the relation; the `HEADQUARTERS` table does not hold any record of the owning `Magazine`. If this were not the case and the `HEADQUARTERS` table held an independent reference to the owning `Magazine` then this would not be a two-sided mapping in Kodo JDO; it would simply be two separate, regular one-to-one mappings through the `Magazine.hq` and `Headquarters.mag` fields.

Notice the use of the `inverse-owner` JDO metadata extension to mark the "owning" side of the relation. Also note that `Headquarters.mag` field simply links the `MAGAZINE` table primary key columns right back to themselves in its `column` attributes, while using the `MAGAZINE` table's foreign key back to `HEADQUARTERS` as its `ref-column` joins.

    Java class:

    public class Magazine
    {
        private Headquarters hq;
        ... class content ...
    }

    public class Headquarters
    {
        private Magazine mag;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint" not-null="true"/>
        <pk column="JDOID"/>
        <column name="HQID" type="bigint"/>
        <fk to-table="HEADQUARTERS">
            <join column="HQID" to-column="ID"/>
        </fk>
        ... columns for magazine fields ...
    </table>

    <table name="HEADQUARTERS">
        <column name="ID" type="bigint"/>
        <pk column="ID"/>
        ... columns for headquarters fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        ... field metadata ...
    </class>

    <class name="Headquarters">
        <field name="mag">
            <extension vendor-name="kodo" key="inverse-owner" value="hq"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="hq">
            <jdbc-field-map type="one-one" column.ID="HQID"/>
        </field>
        ... rest of field mappings ...
    </class>

    <class name="Headquarters">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="mag">
            <jdbc-field-map type="one-one" table="MAGAZINE" ref-column.ID="HQID"
                column.JDOID="JDOID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="hq">
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-one">
                <extension vendor-name="kodo" key="column.ID" value="HQID">
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

    <class name="Headquarters">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="mag">
            <extension vendor-name="kodo" key="inverse-owner" value="hq">
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-one">
                <extension vendor-name="kodo" key="table" value="MAGAZINE"/>
                <extension vendor-name="kodo" key="ref-column.ID" value="HQID"/>
                <extension vendor-name="kodo" key="column.JDOID" value="JDOID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

Example 7.34. Using a One-to-One Mapping With Inverse Columns

In this example, the `Magazine` class no longer has a relation to `Headquarters`. However, the `MAGAZINE` table still has the inverse columns that hold the primary key values of the related `Headquarters` instances. The `Headquarters.mag` field uses these inverse columns. Notice that the mapping data for `Headquarters.mag` is the same in this example as in the previous one; the only difference is the absence of the `inverse-owner` JDO metadata extension.

    Java class:

    public class Headquarters
    {
        private Magazine mag;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint" not-null="true"/>
        <pk column="JDOID"/>
        <column name="HQID" type="bigint"/>
        <fk to-table="HEADQUARTERS">
            <join column="HQID" to-column="ID"/>
        </fk>
        ... columns for magazine fields ...
    </table>

    <table name="HEADQUARTERS">
        <column name="ID" type="bigint"/>
        <pk column="ID"/>
        ... columns for headquarters fields ...
    </table>

    JDO metadata:

    <class name="Headquarters">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Headquarters">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="mag">
            <jdbc-field-map type="one-one" table="MAGAZINE" ref-column.ID="HQID"
                column.JDOID="JDOID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Headquarters">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="mag">
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-one">
                <extension vendor-name="kodo" key="table" value="MAGAZINE"/>
                <extension vendor-name="kodo" key="ref-column.ID" value="HQID"/>
                <extension vendor-name="kodo" key="column.JDOID" value="JDOID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.6. PC One-to-One Mapping

The PC one-to-one mapping is used when a field holds a persistence-capable object of unknown type. It is the default mapping for user-defined interface fields, horizontally mapped classes (Section 7.6.4, “Horizontal Inheritance Mapping”), and fields whose `type` JDO metadata extension is set to `PersistenceCapable`. The mapping uses a single column to hold the stringified value of the related persistent object's oid value. You cannot query across this mapping.

The PC one-to-one mapping has the following attributes:

- `type`: pc

- `column`: The name of the string-compatible column that stores the stringified oid of the related object. This property is required.

- `table`: If the column is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the column is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equievalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

Example 7.35. Using a PC One-to-One Mapping

    Java class:

    public class Magazine
    {
        private IFormat format;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="FORMAT" type="varchar" size="255"/>
        ... columns for magazine fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="format">
            <jdbc-field-map type="pc" column="FORMAT"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="hq">
            <extension vendor-name="kodo" key="jdbc-field-map" value="pc">
                <extension vendor-name="kodo" key="column" value="FORMAT"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.7. Embedded One-to-One Mapping

The embedded one-to-one mapping places the columns needed for the fields of a related object within the owning class' table. This mapping is often used for simple, privately-owned relations, such as a `User` object's relation to its unique `Address`.

The behavior of embedded objects in JDO is different than that of other persistent objects. First, embedded objects do not appear in JDO extents or query results. Also, embedded objects are not shared among owners. If two `User`s reference the same `Address` on commit, each `User` will have a distinct copy of the `Address` when the commit process concludes. You do not call `makePersistent` on embedded objects. Doing so will create a separate, independent instance in the table for the object's class. Simply assigning an object to an embedded field will ensure that it is made persistent and embedded on transaction commit. And finally, when you null an embedded field or assign a new value to the field, it is as if you deleted the old value.

Kodo JDO places very few restrictions on embedded objects. Embedded objects can have all the same field types as other persistent objects, including recursively embedded fields of their own. Classes can have instances that are independently persistent and other instances that are embedded. If you have a class whose instances are always embedded in other objects and never persisted to their own table, you should set the class' `jdbc-class-map-name` JDO metadata extension to `none` to prevent the mapping tool from creating a mapping and table for the class.

There are only two restrictions on embedded fields: an embedded field's declared type must exactly match the type of the embedded value (the embedded object cannot be a subclass of the field's declared type), and fields cannot be embedded in such a way that infinite recursion results. So, for example, a `User` cannot embed another field of type `User`.

Embedded mappings have the properties bulleted below. They also have nested `field` elements, as you will see in the upcoming example.

- `type`: embedded

- `null-ind-column`: The name of the column that differentiates between a null embedded object and an embedded object that happens to have default values for all of its fields. This property is required. The embedded object will be null if the column's value is null. By default, the mapping tool adds a synthetic null indicator column when creating an embedded mapping. You can tell the mapping tool which embedded field's column to use as the null indicator column through the `jdbc-null-ind-name` JDO metadata extension.

- `synthetic`: This property is `true` if the null indicator column is a synthetic column for the sole purpose of determining whether the embedded object is null, or `false` if the null indicator column actually holds data for one of the embedded object's fields.

- `table`: If the embedded object's data is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the embedded object's data is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

Example 7.36. Using an Embedded One-to-One Mapping

Notice that when you map an embedded object, you map all of its fields using nested `field` elements. This process can be recursive.

    Java class:

    public class Magazine
    {
        private ContactInfo contact;
        ... class content ...
    }

    public class ContactInfo
    {
        private String email;
        private String phone;
        private String fax;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        ... primary key columns         ...
        <column name="CONTACT_EMAIL" type="varchar" size="255"/>
        <column name="CONTACT_PHONE" type="varchar" size="15"/>
        <column name="CONTACT_FAX" type="varchar" size="15"/>
        ... columns for magazine fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="contact" embedded="true"/>
        ... rest of field metadata ...
    </class>
    <class name="ContactInfo"/>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="contact">
            <jdbc-field-map type="embedded" null-ind-column="CONTACT_EMAIL"
                synthetic="false">
                <field name="email">
                    <jdbc-field-map type="value" column="CONTACT_EMAIL"/>
                </field>
                <field name="phone">
                    <jdbc-field-map type="value" column="CONTACT_PHONE"/>
                </field>
                <field name="fax">
                    <jdbc-field-map type="value" column="CONTACT_FAX"/>
                </field>
            </jdbc-field-map>
        </field>
        ... rest of field mappings ...
    </class>
    <class name="ContactInfo">
        <jdbc-class-map type="none"/>
        <field name="email">
            <jdbc-field-map type="none"/>
        </field>
        <field name="phone">
            <jdbc-field-map type="none"/>
        </field>
        <field name="fax">
            <jdbc-field-map type="none"/>
        </field>
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="contact" embedded="true">
            <extension vendor-name="kodo" key="jdbc-field-map" value="embedded">
                <extension vendor-name="kodo" key="null-ind-column" value="CONTACT_EMAIL"/>
                <extension vendor-name="kodo" key="synthetic" value="false"/>
                <extension vendor-name="kodo" key="email">
                    <extension vendor-name="kodo" key="jdbc-field-map" value="value">
                        <extension vendor-name="kodo" key="column" value="CONTACT_EMAIL"/>
                    </extension>
                </extension>
                <extension vendor-name="kodo" key="phone">
                    <extension vendor-name="kodo" key="jdbc-field-map" value="value">
                        <extension vendor-name="kodo" key="column" value="CONTACT_PHONE"/>
                    </extension>
                </extension>
                <extension vendor-name="kodo" key="fax">
                    <extension vendor-name="kodo" key="jdbc-field-map" value="value">
                        <extension vendor-name="kodo" key="column" value="CONTACT_FAX"/>
                    </extension>
                </extension>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>
    <class name="ContactInfo">
        <extension vendor-name="kodo" key="jdbc-class-map" value="none"/>
        <field name="email">
            <extension vendor-name="kodo" key="jdbc-field-map" value="none"/>
        </field>
        <field name="phone">
            <extension vendor-name="kodo" key="jdbc-field-map" value="none"/>
        </field>
        <field name="fax">
            <extension vendor-name="kodo" key="jdbc-field-map" value="none"/>
        </field>
    </class>

### 7.9.8. Enumeration Mapping

The enum mapping represents the mapping of a Java 5 `enum` type to a `String`-compatible database column. This mapping stores the enum's name, not its ordinal position. The enum mapping has the following attributes:

- `type`: enum

- `column`: The name of the column that stores the enum name. This property is required.

- `table`: If the column is not in the table listed by the owning class mapping, specify the table name here.

- `ref-column.<pk column>`*: If the column is not in the table listed by the owning class mapping, Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `ref-join-type`: By default, Kodo assumes that when a field value resides in a table other than the class' primary table, this other table always contains a row for each primary table row. Thus Kodo uses a standard inner join when selecting for other-table values, and when inserting a new object Kodo always inserts a row into the other table as well.

  If you set this attribute to `outer`, however, Kodo will not assume that there is a row in this field's table for each row in the class' primary table. Kodo will use outer joins to retrieve the values of this field. Furthermore, Kodo will not insert a row into this field's table unless the field is non-null. When updating an object, the field's row will be deleted if the field value has been set to null (or the equivalent Java default for primitives). Note that Kodo also takes into account other fields that might share a row with this one, so that, for example, the row is only deleted if all fields sharing this table are null for the object in question.

Example 7.37. Using an Enum Mapping

    Java class:

    public class Subscription
    {
    	public enum SubscriptionType
    	{
    		EDUCATIONAL,
    		RESIDENTIAL
    	}

        private SubscriptionType type;
        ... class content ...
    }

    Schema:

    <table name="SUBSCRIPTION">
        ... primary key columns         ...
        <column name="TYPE" type="varchar" size="11"/>
        ... columns for subscription fields ...
    </table>

    JDO metadata:

    <class name="Subscription">
        ... field metadata ...

    	<!-- Since enums are not yet included in the JDO spec as types
    		that should be persistent by default, you must identify
    		enum fields that should be persisted. This behavior may
    		change in a future version of Kodo, in accordance with the
    		JDO2 specification. -->
    	<field name="type" persistence-modifier="persistent"/>
    </class>

    Mapping information using the mapping XML format:

    <class name="Subscription">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="type">
            <jdbc-field-map type="enum" column="TYPE"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Subscription">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="type">
            <extension vendor-name="kodo" key="jdbc-field-map" value="enum">
                <extension vendor-name="kodo" key="column" value="TYPE"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.9. Collection Mapping

The collection mapping maps a collection or array of simple values (primitive wrappers, dates, or strings). It has the following attributes:

- `type`: collection

- `table`: The table where the collection elements are stored. This property is required.

- `element-column`: The column that holds each element value. This property is required.

- `order-column`: The column that holds the position of each element within its collection. This property is optional. By default, the mapping tool orders fields of list or array types, and leaves collection and set fields unordered. You can control whether the mapping tool adds an order column with the `jdbc-ordered` JDO metadata extension.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the collection, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the collection elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.38. Using a Collection Mapping

    Java class:

    public class Magazine
    {
        private Set coverBlubs;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_COVERBLURBS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ELEMENT" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="coverBlurbs">
            <collection element-type="String"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="coverBlurbs">
            <jdbc-field-map type="collection" element-column="ELEMENT"
                table="MAG_COVERBLURBS" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="coverBlurbs">
            <collection element-type="String"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="collection">
                <extension vendor-name="kodo" key="element-column" value="ELEMENT"/>
                <extension vendor-name="kodo" key="table" value="MAG_COVERBLURBS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.10. Many-to-Many Mapping

A many-to-many mapping represents a collection or array of related persistent objects using a join table. Each join table entry holds the primary key values of two related objects.

Many-to-many mappings can be one-sided or two-sided. In the latter case, the two fields involved in the relation both load from the join table. Only the "owning" side of the relation, as indicated by the `inverse-owner` JDO metadata extension, inserts and deletes join table entries, however.

The mapping tool creates many-to-many mappings by default on collections or arrays whose `element-type` is another persistent class, and who do not specify a `inverse-owner` or whose `inverse-owner` is another collection or array.

If your database defines a non-deferred foreign key constraint for the relation, you should be sure to set the kodo.jdbc.ForeignKeyConstraints property appropriately.

The many-to-many mapping has the following attributes:

- `type`: many-many

- `table`: The join table. This property is required.

- `element-column.<pk column>`*: Kodo JDO must be able to join this mapping's columns to the primary key columns of the related object. Each `element-column` attribute joins a column in the join table to the corresponding column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `order-column`: The column that holds the position of each element within its collection. This property is optional. By default, the mapping tool orders fields as list or array types, and leaves collection and set fields unordered. You can control whether the mapping tool adds an order column with the `jdbc-ordered` JDO metadata extension. Only the owning side of a two-sided relation can be ordered.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the collection, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the collection elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.39. Using a Many-to-Many Mapping

    Java class:

    public class Magazine
    {
        private Set articles;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="ARTICLE">
        <column name="TITLE" type="varchar" size="127"/>
        <pk column="TITLE"/>
        ... columns for article fields ...
    </table>

    <table name="MAG_ARTS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ART_TITLE" type="varchar" size="127"/>
        <fk to-table="ARTICLE">
            <join column="ART_TITLE" to-column="TITLE"/>
        </fk>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="articles">
            <collection element-type="Article"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="articles">
            <jdbc-field-map type="many-many" element-column.TITLE="ART_TITLE"
                table="MAG_ARTS" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="articles">
            <collection element-type="Article"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="many-many">
                <extension vendor-name="kodo" key="element-column.TITLE"
                    value="ART_TITLE"/>
                <extension vendor-name="kodo" key="table" value="MAG_ARTS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

Example 7.40. Using a Two-Sided Many-to-Many Mapping

Notice that when we extend the relation to be two-sided in this example, the mappings for the `Magazine.articles` field do not change. The new `Article.magazines` field uses the same join table and simply inverts the `element-column` and `ref-column` in addition to signaling that the `articles` field is the relation's owner.

    Java class:

    public class Magazine
    {
        private Set articles;
        ... class content ...
    }

    public class Article
    {
        private Set magazines;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="ARTICLE">
        <column name="TITLE" type="varchar" size="127"/>
        <pk column="TITLE"/>
        ... columns for article fields ...
    </table>

    <table name="MAG_ARTS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ART_TITLE" type="varchar" size="127"/>
        <fk to-table="ARTICLE">
            <join column="ART_TITLE" to-column="TITLE"/>
        </fk>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="articles">
            <collection element-type="Article"/>
        </field>
        ... rest of field metadata ...
    </class>

    <class name="Article" objectid-class="ArticleId">
        <field name="title" primary-key="true"/>
        <field name="magazines">
            <collection element-type="Magazine"/>
            <extension vendor-name="kodo" key="inverse-owner" value="articles"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="articles">
            <jdbc-field-map type="many-many" element-column.TITLE="ART_TITLE"
                table="MAG_ARTS" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    <class name="Article">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="magazines">
            <jdbc-field-map type="many-many" element-column.JDOID="MAG_ID"
                table="MAG_ARTS" ref-column.TITLE="ART_TITLE"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="articles">
            <collection element-type="Article"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="many-many">
                <extension vendor-name="kodo" key="element-column.TITLE"
                    value="ART_TITLE"/>
                <extension vendor-name="kodo" key="table" value="MAG_ARTS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

    <class name="Article">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="title" primary-key="true"/>
        <field name="magazines">
            <collection element-type="Magazine"/>
            <extension vendor-name="kodo" key="inverse-owner" value="articles"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="many-many">
                <extension vendor-name="kodo" key="element-column.JDOID"
                    value="MAG_ID"/>
                <extension vendor-name="kodo" key="table" value="MAG_ARTS"/>
                <extension vendor-name="kodo" key="ref-column.TITLE" value="ART_TITLE"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.11. One-to-Many Mapping

A one-to-many mapping represents a field that holds a collection or array of related persistent objects, but does not use a join table. Instead, each related object record has a back-reference to its owning instance in the database. In a typical, two-sided one-to-many mapping, this database back-reference manifests itself in Java as a one-to-one relation back to the owning object. This inverse one-to-one is always the `inverse-owner` of the relation. In fact, the mapping tool installs a one-to-many mapping by default only when a collection or array field whose `element-type` is a persistent class declares a one-to-one field as its `inverse-owner`.

You can, however, have one-sided one-to-many mappings in which the back-reference only exists in the database, and is not represented by any Java field. The mapping tool never creates a one-sided one-to-many relation like this; you can only create it by writing the mapping data yourself, and then only on an existing schema that supports it.

If your database defines a non-deferred foreign key constraint for the relation, you should be sure to set the kodo.jdbc.ForeignKeyConstraints property appropriately.

The one-to-many mapping has the following attributes:

- `type`: one-many

- `table`: The table of the related class. This property is required.

- `order-column`: The column that holds the position of each element within its collection. This property is optional. By default, the mapping tool orders fields as list or array types, and leaves collection and set fields unordered. You can control whether the mapping tool adds an order column with the `jdbc-ordered` JDO metadata extension.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the collection, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the collection elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

- `class-criteria`: Whether or not to use the expected class of the related object as a criteria in the SQL issued to select its database record. Typically, this is not needed; Kodo can just use the foreign key value to select the desired record, and if your database data is valid, the record will correspond to an object of the correct class. Under some very rare mappings, however, you may need to select based on both foreign key and class -- for example, if you are using a relation that shares the inverse foreign key with another one-many with elements of a different subclass. In these rare cases, set this attribute to `true` to force Kodo to append class conditions to its SQL.

Example 7.41. Using a One-to-Many Mapping

    Java class:

    public class Magazine
    {
        private Set articles;
        ... class content ...
    }

    public class Article
    {
        private Magazine magazine;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="ARTICLE">
        ... primary key columns        ...
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        ... columns for article fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="articles">
            <collection element-type="Article"/>
            <extension vendor-name="kodo" key="inverse-owner" value="magazine"/>
        </field>
        ... rest of field metadata ...
    </class>

    <class name="Article">
        ... field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="articles">
            <jdbc-field-map type="one-many" table="ARTICLE" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    <class name="Article">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="magazine">
            <jdbc-field-map type="one-one" column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="articles">
            <collection element-type="Article"/>
            <extension vendor-name="kodo" key="inverse-owner" value="magazine"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-many">
                <extension vendor-name="kodo" key="table" value="ARTICLE"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

    <class name="Article">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="magazine">
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-one">
                <extension vendor-name="kodo" key="column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

Example 7.42. Using a One-Sided One-to-Many Mapping

The mappings for `Magazine.articles` are exactly the same in this one-sided relation example. The only difference is that the field no longer declares an `inverse-owner`, because the `Article.magazine` field does not exist in this example.

    Java class:

    public class Magazine
    {
        private Set articles;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="ARTICLE">
        ... primary key columns        ...
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        ... columns for article fields ...
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="articles">
            <collection element-type="Article"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="articles">
            <jdbc-field-map type="one-many" table="ARTICLE" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="articles">
            <collection element-type="Article"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="one-many">
                <extension vendor-name="kodo" key="table" value="ARTICLE"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.12. PC Collection Mapping

Fields that hold a collection or array of persistence-capable objects of an unknown type use the PC collection mapping. It is the default mapping when the `element-type` of a collection or array is a user-defined interface, is a horizontally mapped class (Section 7.6.4, “Horizontal Inheritance Mapping”), or when the `element-type` JDO metadata extension is set to `PersistenceCapable`. The PC collection mapping's schema structure is similar to that of the collection mapping, but the element column stores the stringified value of each related persistent object's oid value. You cannot query across this mapping.

The PC collection mapping has the following attributes:

- `type`: pc-collection

- `table`: The table where the stringified oid values of the collection elements are stored. This property is required.

- `element-column`: The column that holds each stringified oid. This property is required.

- `order-column`: The column that holds the position of each element within its collection. This property is optional. By default, the mapping tool orders fields as list or array types, and leaves collection and set fields unordered. You can control whether the mapping tool adds an order column with the `jdbc-ordered` JDO metadata extension.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the collection, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the collection elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.43. Using a PC Collection Mapping

    Java class:

    public class Magazine
    {
        private Set items;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_ITEMS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ELEMENT" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="items">
            <collection element-type="IMagazineItem"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="items">
            <jdbc-field-map type="pc-collection" element-column="ELEMENT"
                table="MAG_ITEMS" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="items">
            <collection element-type="IMagazineItem"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="pc-collection">
                <extension vendor-name="kodo" key="element-column" value="ELEMENT"/>
                <extension vendor-name="kodo" key="table" value="MAG_ITEMS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.13. Map Mapping

The map mapping represents a map in which the keys and values are simple types (primitive wrappers, dates, or strings). It has the following attributes:

- `type`: map

- `table`: The table where the map entries are stored. This property is required.

- `key-column`: The column that holds each map entry key. This property is required.

- `value-column`: The column that holds each map entry value. This property is required.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.44. Using a Map Mapping

    Java class:

    public class Magazine
    {
        private Map index;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_INDEX">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="TOPIC" type="varchar" size="255"/>
        <column name="PAGENUMBER" type="integer"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="index">
            <map key-type="String" value-type="Integer"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="index">
            <jdbc-field-map type="map" key-column="TOPIC" value-column="PAGENUMBER"
                table="MAG_INDEX" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="index">
            <map key-type="String" value-type="Integer"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="map">
                <extension vendor-name="kodo" key="key-column" value="TOPIC"/>
                <extension vendor-name="kodo" key="value-column" value="PAGENUMBER"/>
                <extension vendor-name="kodo" key="table" value="MAG_INDEX"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.14. N-to-Many Map Mapping

A map field in which the map keys are a simple type (primitive wrapper, string) and the map values are related persistent objects. This mapping has the following attributes:

- `type`: n-many-map

- `table`: The table that holds the map entries. This property is required.

- `key-column`: The column that holds each map entry key. This property is required.

- `value-column.<pk column>`*: Kodo JDO must be able to join this mapping's map value columns to the columns of the related object. Each `value-column` attribute joins a value column in the map table to the corresponding primary key column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.45. Using an N-to-Many Map Mapping

    Java class:

    public class Magazine
    {
        private Map featuredArticles;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="ARTICLE">
        <column name="TITLE" type="varchar" size="127"/>
        <pk column="TITLE"/>
        ... columns for article fields ...
    </table>

    <table name="FEATUREDARTS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="BLURB" type="varchar" size="255"/>
        <column name="ART_TITLE" type="varchar" size="127"/>
        <fk to-table="ARTICLE">
            <join column="ART_TITLE" to-column="TITLE"/>
        </fk>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="featuredArticles">
            <map key-type="String" value-type="Article"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="featuredArticles">
            <jdbc-field-map type="n-many-map" key-column="BLURB"
                value-column.TITLE="ART_TITLE" table="FEATUREDARTS"
                ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="featuredArticles">
            <map key-type="String" value-type="Article"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="n-many-map">
                <extension vendor-name="kodo" key="key-column" value="BLURB"/>
                <extension vendor-name="kodo" key="value-column.TITLE"
                    value="ART_TITLE"/>
                <extension vendor-name="kodo" key="table" value="FEATUREDARTS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.15. Many-to-N Map Mapping

A map field in which the map values are a simple type (primitive wrapper, string) and the map keys are related persistent objects. This mapping has the following attributes:

- `type`: many-n-map

- `table`: The table that holds the map entries. This property is required.

- `key-column.<pk column>`*: Kodo JDO must be able to join this mapping's map key columns to the columns of the related object. Each `key-column` attribute joins a key column in the map table to the corresponding primary key column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `value-column`: The column that holds each map entry value. This property is required.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.46. Using a Many-to-N Map Mapping

    Java class:

    public class Magazine
    {
        private Map images;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="IMAGE">
        <column name="ID" type="bigint"/>
        <pk column="ID"/>
        ... columns for image fields ...
    </table>

    <table name="MAG_IMAGES">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="IMAGE_ID" type="bigint"/>
        <fk to-table="IMAGE">
            <join column="IMAGE_ID" to-column="ID"/>
        </fk>
        <column name="CAPTION" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="images">
            <map key-type="Image" value-type="String"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="featuredArticles">
            <jdbc-field-map type="many-n-map"
                key-column.ID="IMAGE_ID" value-column="CAPTION"
                table="MAG_IMAGES" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="images">
            <map key-type="Image" value-type="String"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="many-n-map">
                <extension vendor-name="kodo" key="key-column.ID" value="IMAGE_ID"/>
                <extension vendor-name="kodo" key="value-column" value="CAPTION"/>
                <extension vendor-name="kodo" key="table" value="MAG_IMAGES"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.16. Many-to-Many Map Mapping

A map in which both the keys and values are relations to other persistent objects use the many-to-many map mapping. This mapping has the following attributes:

- `type`: many-many-map

- `table`: The table that holds the map entries. This property is required.

- `key-column.<pk column>`*: Kodo JDO must be able to join this mapping's map key columns to the columns of the related object. Each `key-column` attribute joins a key column in the map table to the corresponding primary key column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `value-column.<pk column>`*: Kodo JDO must be able to join this mapping's map value columns to the columns of the related object. Each `value-column` attribute joins a value column in the map table to the corresponding primary key column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.47. Using a Many-to-Many Map Mapping

    Java class:

    public class Magazine
    {
        private Map articleImages;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="ARTICLE">
        <column name="TITLE" type="varchar" size="127"/>
        <pk column="TITLE"/>
        ... columns for article fields ...
    </table>

    <table name="IMAGE">
        <column name="ID" type="bigint"/>
        <pk column="ID"/>
        ... columns for image fields ...
    </table>

    <table name="ARTICLEIMAGES">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ART_TITLE" type="varchar" size="127"/>
        <fk to-table="ARTICLE">
            <join column="ART_TITLE" to-column="TITLE"/>
        </fk>
        <column name="IMAGE_ID" type="bigint"/>
        <fk to-table="IMAGE">
            <join column="IMAGE_ID" to-column="ID"/>
        </fk>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="articleImages">
            <map key-type="Article" value-type="Image"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="articleImages">
            <jdbc-field-map type="many-many-map"
                key-column.TITLE="ART_TITLE" value-column.ID="IMAGE_ID"
                table="ARTICLEIMAGES" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="articleImages">
            <map key-type="Article" value-type="Image"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="many-many-map">
                <extension vendor-name="kodo" key="key-column.TITLE"
                    value="ART_TITLE"/>
                <extension vendor-name="kodo" key="value-column.ID"
                    value="IMAGE_ID"/>
                <extension vendor-name="kodo" key="table" value="ARTICLEIMAGES"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.17. PC Map Mapping

A PC map is a map in which both the key and value types are unknown persistence-capable classes. This is the default mapping for maps fields whose `key-type` and `value-type` are user-defined interfaces, horizontally mapped classes (Section 7.6.4, “Horizontal Inheritance Mapping”), or who have set the `key-type, value-type` JDO metadata extensions to `PersistenceCapable`. The key column and value column of this mapping hold the stringified oid value of each map entry's key and value object, respectively.

This mapping has the following attributes:

- `type`: pc-map

- `table`: The table where the map entries are stored. This property is required.

- `key-column`: The column that holds the stringified oid of each map entry key. This property is required.

- `value-column`: The column that holds the stringified oid of each map entry value. This property is required.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.48. Using a PC Map Mapping

    Java class:

    public class Magazine
    {
        private Map items;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_ITEMS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="ITEMTYPE" type="varchar" size="255"/>
        <column name="ITEM" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="items">
            <map key-type="IMagazineItemType" value-type="IMagazineItem"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="items">
            <jdbc-field-map type="pc-map" key-column="ITEMTYPE"
                value-column="ITEM"  table="MAG_ITEMS" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="items">
            <map key-type="IMagazineItemType" value-type="IMagazineItem"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="pc-map">
                <extension vendor-name="kodo" key="key-column" value="ITEMTYPE"/>
                <extension vendor-name="kodo" key="value-column" value="ITEM"/>
                <extension vendor-name="kodo" key="table" value="MAG_ITEMS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.18. N-to-PC Map Mapping

The n-to-PC map mapping represents a map whose keys are a simple type (primitive wrapper, date, string) and whose values are an unknown persistence-capable type. This is the default mapping for maps with simple keys and user-defined interface values, horizontally mapped classes (Section 7.6.4, “Horizontal Inheritance Mapping”), or fields who have set the `value-type` JDO metadata extension to `PersistenceCapable`. The value column of this mapping holds the stringified oid value of each map entry's value object.

This mapping has the following attributes:

- `type`: n-pc-map

- `table`: The table where the map entries are stored. This property is required.

- `key-column`: The column that holds the each map entry key. This property is required.

- `value-column`: The column that holds the stringified oid of each map entry value. This property is required.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.49. Using an N-to-PC Map Mapping

    Java class:

    public class Magazine
    {
        private Map figures;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_FIGURES">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="PAGENUMBER" type="integer"/>
        <column name="FIGURE" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="figures">
            <map key-type="Integer" value-type="IFigure"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="figures">
            <jdbc-field-map type="n-pc-map" key-column="PAGENUMBER"
                value-column="FIGURE"  table="MAG_FIGURES" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="figures">
            <map key-type="Integer" value-type="IFigure"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="n-pc-map">
                <extension vendor-name="kodo" key="key-column" value="PAGENUMBER"/>
                <extension vendor-name="kodo" key="value-column" value="FIGURE"/>
                <extension vendor-name="kodo" key="table" value="MAG_FIGURES"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.19. PC-to-N Map Mapping

The PC-to-n map mapping represents a map whose keys are an unknown persistence-capable type and whose values are a simple type (primitive wrapper, date, string). This is the default mapping for maps with simple values and user-defined interface keys, horizontally mapped classes (Section 7.6.4, “Horizontal Inheritance Mapping”), or fields who have set the `key-type` JDO metadata extension to `PersistenceCapable`. The key column of this mapping holds the stringified oid value of each map entry's key object.

This mapping has the following attributes:

- `type`: pc-n-map

- `table`: The table where the map entries are stored. This property is required.

- `key-column`: The column that holds the stringified oid of each map entry key. This property is required.

- `value-column`: The column that holds each map entry value. This property is required.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.50. Using a PC-to-N Map Mapping

    Java class:

    public class Magazine
    {
        private Map figures;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="MAG_FIGURES">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="FIGURE" type="varchar" size="255"/>
        <column name="CAPTION" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="figures">
            <map key-type="IFigure" value-type="String"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="figures">
            <jdbc-field-map type="pc-n-map" key-column="FIGURE"
                value-column="CAPTION"  table="MAG_FIGURES" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="figures">
            <map key-type="IFigure" value-type="String"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="pc-n-map">
                <extension vendor-name="kodo" key="key-column" value="FIGURE"/>
                <extension vendor-name="kodo" key="value-column" value="CAPTION"/>
                <extension vendor-name="kodo" key="table" value="MAG_FIGURES"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.20. PC-to-Many Map Mapping

A map field in which the map keys are an unknown persistence-capable type and the map values are related persistent objects. Unknown persistence-capable types include user-defined interfaces, horizontally mapped classes (Section 7.6.4, “Horizontal Inheritance Mapping”), and any field whose `key-type` JDO metadata extension is set to `PersistenceCapable`. This mapping has the following attributes:

- `type`: pc-many-map

- `table`: The table that holds the map entries. This property is required.

- `key-column`: The column that holds the stringified oid of each map entry key. This property is required.

- `value-column.<pk column>`*: Kodo JDO must be able to join this mapping's map value columns to the columns of the related object. Each `value-column` attribute joins a value column in the map table to the corresponding primary key column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.51. Using a PC-to-Many Map Mapping

    Java class:

    public class Magazine
    {
        private Map chapterMarkers;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="CHAPTER">
        <column name="TITLE" type="varchar" size="127"/>
        <pk column="TITLE"/>
        ... columns for chapter fields ...
    </table>

    <table name="CHAPTERMARKERS">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="MARKER" type="varchar" size="255"/>
        <column name="CHAPT_TITLE" type="varchar" size="127"/>
        <fk to-table="CHAPTER">
            <join column="CHAPT_TITLE" to-column="TITLE"/>
        </fk>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="chapterMarkers">
            <map key-type="IMarker" value-type="Chapter"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="chapterMarkers">
            <jdbc-field-map type="pc-many-map" key-column="MARKER"
                value-column.TITLE="CHAPT_TITLE" table="CHAPTERMARKERS"
                ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="chapterMarkers">
            <map key-type="IMarker" value-type="Chapter"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="pc-many-map">
                <extension vendor-name="kodo" key="key-column" value="MARKER"/>
                <extension vendor-name="kodo" key="value-column.TITLE"
                    value="CHAPT_TITLE"/>
                <extension vendor-name="kodo" key="table" value="CHAPTERMARKERS"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.21. Many-to-PC Map Mapping

A map field in which the map keys are related persistent objects and the map values are an unknown persistence-capable type. Unknown persistence-capable types include user-defined interfaces, horizontally mapped classes (Section 7.6.4, “Horizontal Inheritance Mapping”), and any field whose `value-type` JDO metadata extension is set to `PersistenceCapable`. This mapping has the following attributes:

- `type`: many-pc-map

- `table`: The table that holds the map entries. This property is required.

- `key-column.<pk column>`*: Kodo JDO must be able to join this mapping's map key columns to the columns of the related object. Each `key-column` attribute joins a key column in the map table to the corresponding primary key column in the table of the related object's class. See the previous discussion of join attributes for details on joins.

- `value-column`: The column that holds the stringified oid of each map entry value. This property is required.

- `ref-column.<pk column>`*: Kodo JDO must be able to join this mapping's table to the table of the owning class. Each `ref-column` attribute joins a column in this mapping's table to the corresponding column in the owning class' table. See the previous discussion of join attributes for details on joins.

- `ref-constant.<column>`*: Similar to the `ref-column` attribute, but used when the join relies on a column in the joined-to table having a constant value. For more information on constant joins, see Section 7.5.2, “Non-Standard Joins”.

- `meta-column`: An optional column that holds metadata about the map, such as whether it is null or simply empty. If present, this column must be able to hold numeric data and must be in the declared table of of the owning class, not the table used to hold the map elements. The mapping tool never adds a metadata column by default, but you can indicate that you would like one with the `jdbc-container-meta` JDO metadata extension.

Example 7.52. Using a Many-to-PC Map Mapping

    Java class:

    public class Magazine
    {
        private Map imageCategories;
        ... class content ...
    }

    Schema:

    <table name="MAGAZINE">
        <column name="JDOID" type="bigint"/>
        <pk column="JDOID"/>
        ... columns for magazine fields ...
    </table>

    <table name="IMAGE">
        <column name="ID" type="bigint"/>
        <pk column="ID"/>
        ... columns for image fields ...
    </table>

    <table name="MAG_IMAGES">
        <column name="MAG_ID" type="bigint"/>
        <fk to-table="MAGAZINE">
            <join column="MAG_ID" to-column="JDOID"/>
        </fk>
        <column name="IMAGE_ID" type="bigint"/>
        <fk to-table="IMAGE">
            <join column="IMAGE_ID" to-column="ID"/>
        </fk>
        <column name="CATEGORY" type="varchar" size="255"/>
    </table>

    JDO metadata:

    <class name="Magazine">
        <field name="images">
            <map key-type="Image" value-type="ICategory"/>
        </field>
        ... rest of field metadata ...
    </class>

    Mapping information using the mapping XML format:

    <class name="Magazine">
        ... class mapping          ...
        ... indicator mappings     ...
        <field name="imageCategories">
            <jdbc-field-map type="many-pc-map"
                key-column.ID="IMAGE_ID" value-column="CATEGORY"
                table="MAG_IMAGES" ref-column.JDOID="MAG_ID"/>
        </field>
        ... rest of field mappings ...
    </class>

    Mapping information using JDO metadata extensions:

    <class name="Magazine">
        ... class extensions       ...
        ... indicator extensions   ...
        <field name="imageCategories">
            <map key-type="Image" value-type="ICategory"/>
            <extension vendor-name="kodo" key="jdbc-field-map" value="many-pc-map">
                <extension vendor-name="kodo" key="key-column.ID" value="IMAGE_ID"/>
                <extension vendor-name="kodo" key="value-column" value="CATEGORY"/>
                <extension vendor-name="kodo" key="table" value="MAG_IMAGES"/>
                <extension vendor-name="kodo" key="ref-column.JDOID" value="MAG_ID"/>
            </extension>
        </field>
        ... rest of field metadata ...
    </class>

### 7.9.22. Custom Field Mapping

Kodo JDO allows you to create your own field mappings. A custom field mapping can override any or all of the CRUD operations for the field: Create, Retrieve, Update, Delete. All mappings must extend, directly or indirectly, from `kodo.jdbc.meta.FieldMapping`.

The `jdbc-field-map-name` JDO metadata extension tells the mapping tool which field mapping to install. If you write mappings by hand rather than with the mapping tool, simply specify the full class name of your custom mapping in the `type` attribute of the mapping XML.

The `samples/ormapping` directory of the Kodo JDO distribution includes examples of custom mappings.

### 7.9.23. Externalization

Object fields that are neither instances of `PersistenceCapable` nor one of the default persistent types mandated by the JDO specification (primitives and wrappers, `String`, `Locale`, etc.) are, by default, persisted to blob mappings by serializing the field value. This has a number of drawbacks:

- Serialization can be slow in some cases.

- Serialized fields can be larger than are necessary in some cases.

- Serialized fields cannot be queried.

- Since the database will store the java serialized bytes, other non-java applications are not able to share the data with the JDO application in a meaningful way.

Kodo offers the ability to write custom field mappings in order to have complete control over the mechanism with which fields are stored, queried, and loaded from the datastore. Often, however, a custom mapping is overkill. Many field types that are not supported by JDO can be easily represented as a type that is directly supported; thus, Kodo provides the externalization service. Externalization allows you to specify methods that will externalize a field value to a supported type on store and then rebuild the value from its externalized form on load.

The field-level externalizer metadata extension contains the name of a method that will be invoked to convert the field into its external form for storage in the database. This extension can take either the name of a non-static method, which will be invoked on the field value, or a static method, which will be invoked with the field value as a parameter. Each method can also take an optional `PersistenceManager` parameter. The return value of the method is the field's external form. By default, Kodo assumes that all named methods belong to the field value's class (or its superclasses). You can, however, specify static methods of other classes using the format `<class-name>.<method-name>`.

Given a field of type `CustomType` that externalizes to a string, the table below demonstrates several possible externalizer methods and their corresponding metadata extensions.

Table 7.1. Externalizer Options

Method | Extension
--- | ---
`public String CustomType.toString()` | `<extension vendor-name="kodo" key="externalizer" value="toString"/>`
`public String CustomType.toString(PersistenceManager pm)` | `<extension vendor-name="kodo" key="externalizer" value="toString"/>`
`public static String AnyClass.toString(CustomType ct)` | `<extension vendor-name="kodo" key="externalizer" value="AnyClass.toString"/>`
`public static String AnyClass.toString(CustomType ct, PersistenceManager pm)` | `<extension vendor-name="kodo" key="externalizer" value="AnyClass.toString"/>`

The field-level factory metadata extension contains the name of a method that will be invoked to instantiate the field from the external form stored in the database. This extension takes a static method name, which will be invoked with the externalized value, and must return an instance of the field type. The method can also take an optional `PersistenceManager` parameter. If this extension is not specified, Kodo will use the constructor of the field type that takes a single argument of the external type, or will throw a `JDOFatalException` if no constructor with that signature exists.

Given a field of type `CustomType` that externalizes to a string, the table below demonstrates several possible factory methods and their corresponding metadata extensions.

Table 7.2. Factory Options

Method | Extension
--- | ---
`public CustomType(String str)` | none
`public static CustomType CustomType.fromString(String str)` | `<extension vendor-name="kodo" key="factory" value="fromString"/>`
`public static CustomType CustomType.fromString(String str, PersistenceManager pm)` | `<extension vendor-name="kodo" key="factory" value="fromString"/>`
`public static CustomType AnyClass.fromString(String str)` | `<extension vendor-name="kodo" key="factory" value="AnyClass.fromString"/>`
`public static CustomType AnyClass.fromString(String str, PersistenceManager pm)` | `<extension vendor-name="kodo" key="factory" value="AnyClass.fromString"/>`

Note that by default, fields whose type is not supported by JDO are neither persistent nor in the default fetch group, so you will have to specify the `persistence-modifier` and `default-fetch-group` metadata attributes explicitly.

| Note
As with fields that are stored through serialization, it is not possible to detect changes to the internal state of the field object. If your field is not a standard JDO type and you change the field object without assigning a new value to the field, you will have to mark the field dirty yourself using `JDOHelper.makeDirty` , unless you have created a custom proxy for the field. See the `samples/proxies` directory for examples of custom proxies.

You can externalize a field to virtually any value that is supported by Kodo's field mappings (the embedded one-to-one mapping is the single exception; you must declare your field to be a persistence-capable type in order to embed it). This means that a field can externalize to something as simple as a primitive, something as complex as a collection or map of persistence-capable objects, or anything in between. If you do choose to externalize to a collection or map, the `element-type`, `key-type`, and `value-type` metadata extensions allow you to specify the corresponding metadata for the externalized form of your field. If the external form of your field is a persistence-capable object, or contains persistence-capable objects, Kodo will correctly include the objects in its persistence-by-reachability algorithms and its delete-dependent algorithms (meaning you can take advantage of the `dependent` family of metadata extensions).

The example below demonstrates a few forms of externalization. See the `samples/externalization` directory of your Kodo distribution for a working example of externalizing many different field types.

Example 7.53. Using Externalization

    public class Magazine
    {
        private Class      cls;
        private URL        url;
        private CustomType customType;

        public static Map mapFromCustomType (CustomType customType)
        {
            ... logic to pack custom type into a map ...
        }

        public static CustomType mapToCustomType (Map map)
        {
            ... logic to create custom type from a map ...
        }

        ... class content ...
    }

    <class name="Magazine">
        <field name="cls" persistence-modifier="persistent"
            default-fetch-group="true">
            <!-- use Class.getName and Class.forName to go to/from strings -->
            <extension vendor-name="kodo" key="externalizer" value="getName"/>
            <extension vendor-name="kodo" key="factory" value="forName"/>
        </field>
        <field name="url" persistence-modifier="persistent"
            default-fetch-group="true">
            <!-- use URL.getexternalForm for externalization; no    -->
            <!-- factory; we can rely on the URL string constructor -->
            <extension vendor-name="kodo" key="externalizer"
                value="toExternalForm"/>
        </field>
        <field name="customType" persistence-modifier="persistent">
            <!-- use our custom methods; notice how we use the  -->
            <!-- key-type and value-type extensions to specify  -->
            <!-- the metadata for our externalized map          -->
            <extension vendor-name="kodo" key="externalizer"
                value="Magazine.mapFromCustomType"/>
            <extension vendor-name="kodo" key="factory"
                value="Magazine.mapToCustomType"/>
            <extension vendor-name="kodo" key="key-type" value="String"/>
            <extension vendor-name="kodo" key="value-type" value="String"/>
        </field>
        ... field metadata ...
    </class>

You can also query externalized fields using parameters. Pass in a value of the field type when executing the query. Kodo will externalize the parameter using the externalize method named in your metadata, and compare the externalized parameter with the externalized value stored in the database. As a shortcut, Kodo also allows you to use parameters or literals of the field's externalized type in queries, as demonstrated in the example below.

| Note
Currently, queries are limited to fields that externalize to a primitive, primitive wrapper, string, or date, due to constraints on query syntax.

Example 7.54. Querying Externalization Fields

Assume the `Magazine` class has the same fields as in the previous example.

    // you can query using parameters
    Query q = pm.newQuery (Magazine.class, "url == :u");
    Collection results = (Collection)
        q.execute (new URL ("http://www.solarmetric.com"));

    // or as a shortcut, you can use the externalized form directly
    q = pm.newQuery (Magazine.class, "url == 'http://www.solarmetric.com'");
    results = (Collection) q.execute ();

### 7.9.24. External Values

Externalization often takes simple constant values and transforms them to constant values of a different type. An example would be storing a `boolean` field as a `char`, where `true` and `false` would be stored in the database as `'T'` and `'F'` respectively.

Kodo allows the ability to define these constant values in metadata, so that the field will behave like field externalization without requiring a custom externalizer/factory. External values supports translation of pre-defined simple types (primitives, primitive wrappers, Dates, and Strings), to other pre-defined simple typed values.

All constant values must be defined in the `external-values` field extension. The values are defined in a simlar format as configuration plugins, except that the value pairs are Java and datastore values respectively. Extending the previous example, one would use the extension value: `true=T,false=F`. If the datatype of the datastore value is different from the field's, the datastore type can be defined using the `type` field extension.

Example 7.55. Using External Values

This example uses the `external-values` and `type` field extension to transform a String field to an integer at the database.

    public class Magazine
    {
    	private String	sizeWidth;
    	.... class content ...
    }

    Schema:

    <table name="MAGAZINE">
    	... primary key columns			...
    	<column name="SIZE_WIDTH" type="integer"/>
    	... columns for magazine fields	...
    </table>

    JDO metadata:

    <class name="Magazine">
    	<field name="sizeWidth">
    		<extension vendor-name="kodo" key="type" value="int"/>
    		<extension vendor-name="kodo" key="external-values"
    			value="SMALL=5,MEDIUM=8,LARGE=10"/>
    	</field>
    	... field metadata ...
    </class>

Prev | Up | Next
7.8. Class Indicator | Home | Chapter 8. Schema Information