7.10. Custom Mappings

7.10.1. Custom Class Mapping
7.10.2. Custom Discriminator and Version Strategies
7.10.3. Custom Field Mapping
7.10.3.1. Value Handlers
7.10.3.2. Field Strategies
7.10.3.3. Configuration

In Kodo, you are not limited to the set of standard mappings defined by the specification. Kodo allows you to define custom class, discriminator, version, and field mapping strategies with all the power of Kodo's built-in strategies. Section 1.3.5, “Custom Mappings” describes custom mapping samples that ship with Kodo.

7.10.1. Custom Class Mapping

To create a custom class mapping, write an implementation of the kodo.jdbc.meta.ClassStrategy interface. You will probably want to extend one of the existing abstract or concrete strategies in the kodo.jdbc.meta.strats package.

The org.apache.openjpa.persistence.jdbc.Strategy annotation allows you to declare a custom class mapping strategy in JPA mapping metadata. Set the value of the annotation to the full class name of your custom strategy. You specify custom strategies in JDO by setting the inheritance element's strategy attribute to the full class name of your implementation. You can configure your strategy class' bean properties using Kodo's plugin syntax, detailed in Section 2.4, “Plugin Configuration”.

7.10.2. Custom Discriminator and Version Strategies

To define a custom discriminator or version strategy, implement the kodo.jdbc.meta.DiscriminatorStrategy or kodo.jdbc.meta.VersionStrategy interface, respectively. You might extend one of the existing abstract or concrete strategies in the kodo.jdbc.meta.strats package.

Kodo includes the org.apache.openjpa.persistence.jdbc.DiscriminatorStrategy and kodo.persistence.jdbc.VersionStrategy class annotations for declaring a custom discriminator or version strategy in JPA mapping metadata. Set the string value of these annotations to the full class name of your implementation, or to the class name or alias of an existing Kodo implementation.

To specify your custom strategy in JDO metadata, set the appropriate strategy attribute to the full class name of your implementation. To use a custom discriminator strategy, specify its class name in the discriminator element's strategy attribute. To use a custom version strategy, specify its class name in the version element's strategy attribute.

As with custom class mappings, you can configure your strategy class' bean properties using Kodo's plugin syntax, detailed in Section 2.4, “Plugin Configuration”.

7.10.3. Custom Field Mapping

While custom class, discriminator, and version mapping can be useful, custom field mappings are far more common. Kodo offers two types of custom field mappings: value handlers, and full custom field strategies. The following sections examine each.

7.10.3.1. Value Handlers

Value handlers make it trivial to map any type that you can break down into one or more simple values. All value handlers implement the kodo.jdbc.meta.ValueHandler interface. Rather than give synthetic examples of value handlers, Kodo provides the source to most of the built-in handlers in the src/kodo/jdbc/meta/strats directory of your Kodo distribution. Use these functional implementations as examples when you create your own value handlers.

Note that value handlers are not only simple to write, but are highly reusable. For example, imagine that you create a handler for java.awt.Point values. You can not only use this handler to map fields of type Point, but also to map Collections or Maps of Points with no additional work.

7.10.3.2. Field Strategies

Kodo interacts with persistent fields through the kodo.jdbc.meta.FieldStrategy interface. You can implement this interface yourself to create a custom field strategy, or extend one of the existing abstract or concrete strategies in the kodo.jdbc.meta.strats package. Creating a custom field strategy is more difficult than writing a custom value handler, but gives you more freedom in how you interact with the database. Section 1.3.5, “Custom Mappings” describes custom mapping samples that ship with Kodo.

7.10.3.3. Configuration

Kodo gives you two ways to configure your custom field mappings. The FieldStrategies property of the built-in MappingDefaults implementations allows you to globally associate field types with their corresponding custom value handler or strategy. Kodo will automatically use your custom strategies when it encounters a field of the associated type. Kodo will use your custom value handlers whenever it encounters a field, collection element, map key, or map value of the associated type. Section 7.4, “Mapping Defaults” described mapping defaults in detail.

Your other option is to explicitly install a custom value handler or strategy on a particular field. To do so, specify the full name of your implementation class in the proper mapping metadata extension. Kodo JPA includes the org.apache.openjpa.persistence.jdbc.Strategy, kodo.persistence.jdbc.ElementStrategy, and kodo.persistence.jdbc.KeyStrategy annotations. Kodo JDO recognizes jdbc-strategy, jdbc-element-strategy, jdbc-key-strategy, and jdbc-value-strategy field extension keys. You can configure the named strategy or handler's bean properties in these extensions using Kodo's plugin format (see Section 2.4, “Plugin Configuration”).

The example below installs a custom strategy on the coverImage field, uses a custom value handler for the primaryInfoStruct field, and uses the same value handler for the elements of the secondaryInfoStructs collection.

Example 7.34. Custom Mappings via Extensions

JPA:

import kodo.persistence.jdbc.*;
import org.apache.openjpa.persistence.*;
import org.apache.openjpa.persistence.jdbc.*;

@Entity
public class Magazine
{
    @Persistent
    @Strategy("org.mag.mapping.ImageStrategy")
    @Column(name="IMG")
    private Image coverImage;
 
    @Persistent
    @Strategy("org.mag.mapping.InfoStructHandler")
    @Columns({
        @Column(name="DATA1"),
        @Column(name="DATA2"),
        @Column(name="DATA3")
    })
    private InfoStruct primaryInfoStruct;

    @PersistentCollection
    @ContainerTable(name="SEC_STRUCTS", joinColumns=@XJoinColumn(name="MAG_ID"))
    @ElementStrategy("org.mag.mapping.InfoStructHandler")
    @ElementColumns({
        @ElementColumn(name="DATA1"),
        @ElementColumn(name="DATA2"),
        @ElementColumn(name="DATA3")
    })
    private Collection<InfoStruct> secondaryInfoStructs;

    ...
}

JDO:

<?xml version="1.0"?>
<orm>
    <package name="org.mag">
        <class name="Magazine" table="MAG">
            <field name="coverImage" column="IMG">
                <extension vendor-name="kodo" key="jdbc-strategy"
                    value="org.mag.mapping.ImageStrategy"/>
            </field>
            <field name="primaryInfoStruct">
                <column name="DATA1"/>
                <column name="DATA2"/>
                <column name="DATA3"/>
                <extension vendor-name="kodo" key="jdbc-strategy"
                    value="org.mag.mapping.InfoStructHandler"/>
            </field>
            <field name="secondaryInfoStructs" table="SEC_STRUCTS">
                <join column="MAG_ID"/>
                <element>
                    <column name="DATA1"/>
                    <column name="DATA2"/>
                    <column name="DATA3"/>
                </element>
                <extension vendor-name="kodo" key="jdbc-element-strategy"
                    value="org.mag.mapping.InfoStructHandler"/>
            </field>
            ...
        </class>
    </package>
</orm>

 

Skip navigation bar   Back to Top