JDO requires that implementations support the persistence of interfaces as first class objects (FCO's).
DataNucleus provides this capability. It follows the same general process as for
java.lang.Object since both interfaces and java.lang.Object are basically
references
to some persistable object.
Let's suppose you have an interface with a selection of classes implementing the interface something
like this
You then have a class that contains an object of this interface type
public class ShapeHolder
{
protected Shape shape=null;
...
}
To allow persistence of this interface field with DataNucleus you have 2 levels of control. The first level
is global control. Since all of our
Square
,
Circle
,
Rectangle
classes
implements
Shape
then we just define them in the MetaData as we would normally.
<package name="com.mydomain.samples.shape">
<class name="Square">
...
</class>
<class name="Circle">
...
</class>
<class name="Rectangle">
...
</class>
</package>
The global way means that when mapping that field DataNucleus will look at all PersistenceCapable classes
it knows about that implement the specified interface.
JDO2 also allows users to specify a list of classes implementing the interface on a field-by-field
basis, defining which of these implementations are accepted for a particular interface
field. To do this you define the Meta-Data like this
<package name="com.mydomain.samples.shape">
<class name="ShapeHolder">
<field name="shape" persistence-modifier="persistent"
field-type="com.mydomain.samples.shape.Circle,
com.mydomain.samples.shape.Rectangle,
com.mydomain.samples.shape.Square"/>
</class>
That is, for any interface object in a class to be persisted, you define the possible implementation
classes that can be stored there. DataNucleus interprets this information and will map the above example
classes to the following in the database
So DataNucleus adds foreign keys from the containers table to all of the possible implementation tables for
the
shape
field.
You can have a Collection/Map containing elements of an interface type. You specify this in the same
way as you would any Collection/Map. You can have a Collection of interfaces as long as you use a
join table relation and it is unidirectional. You need to use a DataNucleus extension tag
"implementation-classes" if you want to restrict the collection to only contain particular
implementations of an interface.