7.5. Mapping Notes

7.5.1. Join Attributes
7.5.2. Non-Standard Joins

Kodo JDO divides mappings into four functional categories: class mappings, version indicators, class indicators, and field mappings. The remainder of this chapter explores each category in turn. Examples are given for all of the mapping types Kodo JDO supports. These examples present the following information:

7.5.1. Join Attributes

Many mappings have attributes that join one column to another. For example, if persistent class Person has a field of persistent type Address, you might model the relationship using a one-to-one mapping. In this mapping, the PERSON table includes columns to hold the primary key values of each related address. To retrieve a person's address, Kodo joins these PERSON table columns to the primary key columns of the ADDRESS table, as depicted below.

<table name="PERSON">
    <pk column="ID"/>
    <column name="ID" type="bigint" not-null="true"/>
    <column name="ADDRESS_PK1" type="integer"/>
    <column name="ADDRESS_PK2" type="varchar" size="255"/>
    <fk to-table="ADDRESS">
        <join column="ADDRESS_PK1" to-column="PK1"/>
        <join column="ADDRESS_PK2" to-column="PK2"/>
    </fk>
    ... other columns ...
</table>
<table name="ADDRESS">
    <pk>
        <on column="PK1"/>
        <on column="PK2"/>
    </pk>
    <column name="PK1" type="integer" not-null="true"/>
    <column name="PK2" type="varchar" size="255" not-null="true"/>
    ... other columns ...
</table>

SELECT ADDRESS.PK1, ADDRESS.PK2, ...
  FROM PERSON INNER JOIN ADDRESS
    ON PERSON.ADDRESS_PK1 = ADDRESS.PK1 
   AND PERSON.ADDRESS_PK2 = ADDRESS.PK2
 WHERE PERSON.ID = ?

Mappings that use joins must record these joins in their XML representations. To accomplish this, they use XML attributes of the form <attribute name>.<pk-column>="<local column>". For relationship columns, the attribute name is typically just column. Therefore, the attributes representing the joins in our example would be:

  • column.PK1="ADDRESS_PK1"

  • column.PK2="ADDRESS_PK2"

When reading these attributes to yourself, replacing the '.' with the word "for" and the '=' with the word "is" may help you understand their meaning. Thus, the attributes above become:

  • The column for PK1 is ADDRESS_PK1.

  • The column for PK2 is ADDRESS_PK2.

Below we present the complete mapping XML for our one-to-one field. All mappings are detailed later in this chapter.

<jdbc-field-map type="one-one" column.PK1="ADDRESS_PK1" 
    column.PK2="ADDRESS_PK2"/>

7.5.2. Non-Standard Joins

The example in the previous section uses a "standard" join, in that there is one PERSON table column for each primary key column in the ADDRESS table. Kodo does, however, support other join patterns, including partial primary key joins, non-primary key joins, and joins using constant values.

In a partial primary key join, the local table only has columns for a subset of the primary key columns in the table it joins to. So long as this subset of columns correctly identifies the proper row(s) in the referenced table, Kodo will function properly. There is no special syntax for expressing a partial primary key join in Kodo's XML mapping format -- just do not include XML attributes for primary key columns that are not used in the join.

In a non-primary key join, at least one of the columns being joined to is not a primary key. Once again, Kodo supports this join type with the same syntax as a primary key join. There is one restriction, however: each non-primary key column you are joining to must be controlled by a field mapping that implements the kodo.jdbc.meta.JoinableMapping interface. The built-in value mapping implements this interface, meaning that any column mapped to a primitive/primitive wrapper/Date/string can be joined to. Kodo will also respect any custom mappings that implement this interface.

Not all joins consist of only links between columns. In some cases you might have a schema in which one of the join criterions is that a column in the referenced table must have some constant value. Lets modify our previous person/address example to use a constant value join. The sample below depicts modified versions of the PERSON and ADDRESS tables and the corresponding SQL to retrieve a person's address. Notice the use of the 'P' constant.

<table name="PERSON">
    <pk column="ID"/>
    <column name="ID" type="bigint" not-null="true"/>
    <column name="ADDRESS_ID" type="integer"/>
    <fk to-table="ADDRESS">
        <join column="ADDRESS_ID" to-column="ADDRID"/>
        <join value="'P'" to-column="TYPE"/>
    </fk>
    ... other columns ...
</table>
<table name="ADDRESS">
    <pk>
        <on column="ADDRID"/>
        <on column="TYPE"/>
    </pk>
    <!-- the pk is made up of an id integer and an address type, which -->
    <!-- can be set to either 'P' for a person's address, or 'C' for   -->
    <!-- a company's address                                           -->
    <column name="ADDRID" type="integer" not-null="true"/>
    <column name="TYPE" type="char" size="1" not-null="true"/>
    ... other columns ...
</table>

SELECT ADDRESS.ADDRID, ADDRESS.TYPE, ...
  FROM PERSON INNER JOIN ADDRESS
    ON PERSON.ADDRESS_ID = ADDRESS.ADDRID 
   AND ADDRESS.TYPE = 'P'
 WHERE PERSON.ID = ?

To express these conditions as XML join attributes, simply write the appropriate constant value as the attribute value in the now-familiar syntax:

  • column.ADDRID="ADDRESS_ID"

  • column.TYPE="'P'"

Constant join values can be either strings or numbers. If the value is a string, be sure to place single quotes around it as we did above.