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.
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”.
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”.
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.
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
Collection
s or Map
s of
Point
s with no additional work.
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.
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>