Kodo extends standard metadata to allow you to access advanced Kodo functionality. This section covers persistence metadata extensions; we discuss mapping metadata extensions in Section 7.9, “Mapping Extensions”. All metadata extensions are optional; Kodo will rely on its defaults when no explicit data is provided.
In JDO metadata, Kodo extensions are expresses with standard JDO
extension
elements. All Kodo extensions use a
vendor-name
of kodo
. The next
sections present a list of the available class
and field
element extension keys.
Kodo recognizes the following class extensions:
JDO standardizes fetch group definition with the
the fetch-group
XML mapping element.
Fetch groups, however, are not part of the JPA standard.
The
kodo.persistence.FetchGroups
and
kodo.persistence.FetchGroup
annotations allow you to define fetch groups in your JPA
entities. Section 5.6, “Fetch Groups” discusses Kodo's
support for fetch groups in general; see
Section 5.6.1, “Custom Fetch Groups” for how to use these
annotations in particular.
Section 10.1, “Data Cache” examines caching in Kodo. Metadata extensions allow individual classes to override system caching defaults.
Kodo JPA defines the
kodo.persistence.DataCache
annotation for caching information. This annotation has the
following properties:
boolean enabled
: Whether to cache
data for instances of the class. Defaults to
true
for base classes, or the
superclass value for subclasses. If you set this
property to false
, all other
properties are ignored.
String name
: Place data for instances
of the class in a named cache. By default, instance
data is placed in the same cache as superclass data, or
the default cache configured through
the
kodo.DataCache
configuration property
for base classes.
int timeout
: The number of
milliseconds data for the class remains valid. Use
-1 for no timeout. Defaults to the
kodo.DataCacheTimeout
property value.
Kodo JDO uses the data-cache
and
data-cache-timeout
XML extension keys to
specify class caching information. The
data-cache-timeout
key sets the number
of milliseconds cached data for an instance remains valid. A
value of -1 means never to expire instance data. This
extension overrides the
kodo.DataCacheTimeout
configuration
property.
The data-cache
key accepts the
following values:
true
: Use the default cache, as
configured by the
kodo.DataCache
configuration
property. This is the default when no extension is
given, unless a superclass names a different cache.
false
: Data for instances of this
class should not be cached.
<cache-name>
: Place data for
instances of this class into the cache with name
<cache-name>
.
The Kodo enhancer may add a synthetic field to detachable classes to hold detached state (see Section 11.1.3, “Defining the Detached Object Graph” for details). You can instead declare your own detached state field or supress the creation of a detached state field altogether. In the latter case, your class must not use datastore identity, and should declare a version field to detect optimistic concurrency errors during detached modifications.
Kodo JPA defines the
kodo.persistence.DetachedState
annotation for controlling detached state. When used
to annotate a class, DetachedState
recognizes the following properties:
boolean enabled
: Set to false to
suppress the use of detached state.
String fieldName
: Use this property
to declare your own detached state field. The field
must be of type Object
.
Typically this property is only used if the field is
inherited from a non-persisted superclass. If the field
is declared in your entity class, you will typically
annotate the field directly, as described below.
If you declare your own detached state field, you can annotate
that field with DetachedState
directly,
rather than placing the annotation at the class level and using
the fieldName
property. When placed on a
field, DetachedState
acts as a marker
annotation; it does not recognize any properties. Your
annotated field must be of type Object
.
The JDO detached-state-field
extension key
names the Object
field used to store an
object's detached state information. Set this extension to the
name of a field in your class, or to
false
to disable the use of detached state.
Kodo requires you to pre-declare subclass lock groups in the
least-derived mapped class.
The JPA
kodo.persistence.LockGroups
annotation accepts an array of lock group names.
The JDO lock-groups
XML extension key accepts
a string of comma-separated lock group names.
For details on lock groups, see
Section 5.8.1, “Lock Groups and Subclasses”.
Kodo recognizes the following field extensions:
In a dependent relation, the referenced
object is deleted whenever the owning object is deleted, or
whenever the relation is severed by nulling or resetting the
owning field. For example, if the
Magazine.coverArticle
field is marked
dependent, then setting Magazine.coverArticle
to a new Article
instance will
automatically delete the old Article
stored in the field. Similarly, deleting a Magazine
object will automatically delete its current cover
Article
.
You can prevent an orphaned dependent object from being deleted
by assigning it to another relation in the same transaction.
JDO standardizes support for dependent relations with the
dependent
attribute of the XML
field
element, and the
dependent-element
, dependent-key
,
and dependent-value
attribues of the
collection
and map
elements.
Kodo JPA offers a family of marker annotations to
denote dependent relations in JPA entities:
kodo.persistence.Dependent
: Marks
a direct relation as dependent.
kodo.persistence.ElementDependent
:
Marks the entity elements of a collection, array, or
map field as dependent.
kodo.persistence.KeyDependent
:
Marks the key entities in a map field as dependent.
This boolean extension, denoted by
the JPA
kodo.persistence.LRS
annotation,
or
the JDO lrs
metadata extension key,
indicates that a field should use
Kodo's special large result set collection or map proxies.
A complete description of large result set proxies is
available in Section 5.5.4.2, “Large Result Set Proxies”.
The JPA Overview's
Section 5.2.12, “Order By” describes JPA's
OrderBy
annotation for loading the elements
of collection fields in a prescribed order.
The JDO order-by
metadata extension
serves the same function.
Ordering syntax is as follows:
#element|<field name>[ asc|ascending|desc|descending][, ...]
The token #element
represents the element
value. Simple element types such as strings and primitive
wrappers are sorted based on their natural ordering. If the
collection holds persistent objects, its elements are sorted
based on the natural ordering of the objects' primary key
values. By substituting a field name for the
#element
token, you can order a collection of
persistent objects by an arbitrary field in the related type,
rather than by primary key.
The field name or #element
token may be
followed by the keywords asc/ascending
or
desc/descending
in either all-upper or
all-lower case to mandate ascending and descending order.
If the direction is omitted, Kodo defaults to ascending order.
Note that the defined ordering is only applied when the collection is loaded from the datastore. It is not maintained by Kodo as you modify the collection in memory.
The following ordering string orders a collection by its element values in descending order:
"#element desc"
The following ordering string orders a collection of
Author
objects by each author's last
name in ascending order. If two last names are equal, the
authors are ordered by first name in ascending order.
"firstName, lastName"
This extension names the inverse field in a logical
bidirectional relation.
To create a logical bidrectional relation in Kodo JPA, use the
kodo.persistence.InverseLogical
annotation.
To create a logical bidrectional relation in Kodo JDO, use the
inverse-logical
XML extension key.
We discuss logical bidirectional relations and this extension
in detail in Section 5.4, “Managed Inverses”.
Lock groups allow for fine-grained optimistic locking
concurrency.
Use
Kodo JPA's
kodo.persistence.LockGroup
annotation
or
Kodo JDO's lock-group
extension key
to name the lock group for a field. You can exclude a field
from optimistic locking with a value of none
.
We discuss lock groups and this extension further in
Section 5.8, “Lock Groups”.
The read-only extension makes a field unwritable. The extension only applies to existing persistent objects; new object fields are always writeable.
To mark a field read-only in JPA metadata, set the
kodo.persistence.ReadOnly
annotation to a
kodo.persistence.UpdateAction
enum value. The UpdateAction
enum
includes:
UpdateAction.IGNORE
: Updates to the
field are completely ignored. The field is not
considered dirty.
The new value will not even get stored in the
Kodo data cache.
UpdateAction.RESTRICT
: Any attempt
to change the field will result in an immediate
exception.
To mark a field read-only in JDO metadata, set the
read-only
extension key to one of the
following values:
ignore
: Updates to the field are
completely ignored. The field is not considered dirty.
The new value will not even get stored in the
Kodo data cache.
restrict
: Any attempt to change the
field will result in an immediate exception.
Kodo has three levels of support for relations:
Relations that hold a reference to an object of a concrete persistent class are supported by storing the primary key values of the related instance in the database.
Relations that hold a reference to an object of an unknown persistent class are supported by storing the stringified identity value of the related instance. This level of support does not allow queries across the relation.
Relations that hold an unknown object or interface. The only way to support these relations is to serialize their value to the database. This does not allow you to query the field, and is not very efficient.
Clearly, when you declare a field's type to be another
persistence-capable class, Kodo uses level 1 support.
By default, Kodo assumes that any interface-typed fields
you declare will be implemented only by other persistent
classes, and assigns interfaces level 2 support. The exception
to this rule is the java.io.Serializable
interface. If you declare a field to be of type
Serializable
, Kodo lumps it
together with java.lang.Object
fields and other non-interface, unrecognized field types,
which are all assigned level 3 support.
With Kodo's type family of metadata extensions, you can
control the level of support given to your
unknown/interface-typed fields. Setting the value of this
extension to
Entity
in JPA or
PersistenceCapable
in JDO
indicates that the field value will always be some persistent
object, and gives level 2 support. Setting the value of this
extension to the class of a concrete persistent
type is even better; it gives you level 1
support (just as if you had declared your field to be
of that type in the first place). Setting this extension
to Object
uses level 3
support. This is useful when you have an interface
relation that may not
hold other persistent objects (recall that Kodo
assumes interface fields will always hold persistent
instances by default).
This extension is also used with Kodo's externalization feature, described in Section 5.5.5, “Externalization”.
Kodo JPA defines the following type annotations for field values, collection, array, and map elements, and map keys, respectively:
kodo.persistence.Type
kodo.persistence.ElementType
kodo.persistence.KeyType
Kodo JDO defines the following type extension keys for field values, collection and array elements, map entry keys, and map entry values, respectively:
type
element-type
key-type
value-type
The
JPA
kodo.persistence.Externalizer
annotation
or
JDO externalizer
extension key
names a method to transform a field value into a value of
another type. See Section 5.5.5, “Externalization”
for details.
The
JPA
kodo.persistence.Factory
annotation
or
JDO factory
extension key
names a method to re-create a field value from its
externalized form. See Section 5.5.5, “Externalization”
for details.
The
JPA
kodo.persistence.ExternalValues
annotation
or
JDO external-values
extension key
declares values for transformation of simple fields
to different constant values in the datastore.
See Section 5.5.5.1, “External Values” for details.
The following example shows you how to specify extensions in metadata.
Example 6.4. Kodo Metadata Extensions
JPA:
import kodo.persistence.*; @Entity @DataCache(enabled=false) public class Magazine { @ManyToMany @LRS @LockGroup(LockGroup.NONE) private Collection<Subscriber> subscribers; @ExternalValues({"true=1", "false=2"}) @Type(int.class) private boolean weekly; @PersistentCollection @OrderBy("#element DESC") private List<String> subtitles; ... }
JDO:
<jdo> <package name="org.mag"> <class name="Magazine"> <extension vendor-name="kodo" key="data-cache" value="false"/> <field name="subscribers"> <collection element-type="Subscriber"/> <extension vendor-name="kodo" key="lrs" value="true"/> <extension vendor-name="kodo" key="lock-group" value="none"/> </field> <field name="weekly"> <extension vendor-name="kodo" key="external-values" value="true=1,false=2"/> <extension vendor-name="kodo" key="type" value="int"/> </field> <field name="subtitles"> <collection element-type="string"/> <extension vendor-name="kodo" key="order-by" value="#element desc"/> </field> </class> </package> </jdo>
![]() ![]() |