7.8. Field Mapping

7.8.1. Value Mapping
7.8.2. Blob Mapping
7.8.3. Clob Mapping
7.8.4. Byte Array Mapping
7.8.5. One-to-One Mapping
7.8.6. PC One-to-One Mapping
7.8.7. Embedded One-to-One Mapping
7.8.8. Collection Mapping
7.8.9. Many-to-Many Mapping
7.8.10. One-to-Many Mapping
7.8.11. PC Collection Mapping
7.8.12. Map Mapping
7.8.13. N-to-Many Map Mapping
7.8.14. Many-to-N Map Mapping
7.8.15. Many-to-Many Map Mapping
7.8.16. PC Map Mapping
7.8.17. N-to-PC Map Mapping
7.8.18. PC-to-N Map Mapping
7.8.19. PC-to-Many Map Mapping
7.8.20. Many-to-PC Map Mapping
7.8.21. Custom Field Mapping
7.8.22. Externalization

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.8.22, “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.8.1. Value Mapping

The value mapping represents the direct mapping of a Java primitive, primitive wrapper, 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.4.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.20. 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.21. 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.8.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.4.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.22. 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.8.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.4.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.23. 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.8.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.4.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.24. 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.8.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.

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.4.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.25. 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.26. 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.map 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.27.  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.8.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 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.4.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.28. 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.8.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 Users 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.4.2, “Non-Standard Joins”.

Example 7.29. 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">
        <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.8.8. Collection Mapping

The collection mapping maps a collection or array of simple values (primitive wrappers 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.4.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.30. 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.8.9. 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. 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.4.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.31. 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.32. 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.8.10. 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.

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.4.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.33. 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.34. 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.8.11. 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, 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.4.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.35. 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.8.12. Map Mapping

The map mapping represents a map in which the keys and values are simple types (primitive wrappers 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.4.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.36. 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.8.13. 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.4.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.37. 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.8.14. 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.4.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.38. 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.8.15. 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.4.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.39. 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.8.16. 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, 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.4.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.40. 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.8.17. N-to-PC Map Mapping

The n-to-PC map mapping represents a map whose keys are a simple type (primitive wrapper, 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, 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.4.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.41. 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.8.18. 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, string). This is the default mapping for maps with simple values and user-defined interface keys, 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.4.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.42. 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.8.19. 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 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.4.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.43. 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.8.20. 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 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.4.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 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.8.21. 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.8.22. 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

MethodExtension
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

MethodExtension
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]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.45. 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. Declare the parameter to be the actual field type, and pass in a value of that 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]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.46. 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);
q.declareParameters ("java.net.URL u");
q.setFilter ("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 ();