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:
A sample Java class definition supporting the relevant mapping.
The hypothetical schema being used. The schema is given in Kodo JDO's XML format for schema information.
JDO metadata for the mapping's class or field.
The mapping information in the XML format used by the file mapping factory and other mapping tools. Remember that the mapping tool generally writes this mapping information for you. The examples include this information so that you can create and modify mappings by hand if you so desire.
The same mapping information, presented as JDO metadata extensions used by the metadata mapping factory. This is for users who have chosen to use the metadata mapping factory, and want to understand mappings so they can create and modify them by hand.
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:
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"/>
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:
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.