# Metadata

The JPA Overview covers JPA metadata in . This chapter discusses OpenJPA's extensions to standard JPA metadata.

## Metadata Factory

The `openjpa.MetaDataFactory` configuration property controls metadata loading and storing. This property takes a plugin string (see ) describing a concrete org.apache.openjpa.meta.MetaDataFactory implementation. A metadata factory can load mapping information as well as persistence metadata, or it can leave mapping information to a separate mapping factory (see ). OpenJPA recognizes the following built-in metadata factories:

- `jpa`: Standard JPA metadata. This is an alias for the org.apache.openjpa.persistence.PersistenceMetaDataFactory.

JPA has built-in settings for listing your persistent classes, which the JPA Overview describes. OpenJPA supports these JPA standard settings by translating them into its own internal metadata factory properties. Each internal property represents a different mechanism for locating persistent types; you can choose the mechanism or combination of mechanisms that are most convenient. See for a discussion of when it is necessary to list your persistent classes.

- `Types`: A semicolon-separated list of fully-qualified persistent class names.

- `Resources`: A semicolon-separated list of resource paths to metadata files or jar archives. Each jar archive will be scanned for annotated JPA entities.

- `URLs`: A semicolon-separated list of URLs of metadata files or jar archives. Each jar archive will be scanned for annotated JPA entities.

- `ClasspathScan`: A semicolon-separated list of directories or jar archives listed in your classpath. Each directory and jar archive will be scanned for annotated JPA entities.

Setting a Standard Metadata Factory

    <property name="openjpa.MetaDataFactory" value="jpa(ClasspathScan=build;lib.jar)"/>

Setting a Custom Metadata Factory

    <property name="openjpa.MetaDataFactory" value="com.xyz.CustomMetaDataFactory"/>

metadata loading and storing MetaDataFactory

The openjpa.MetaDataRepository configuration property controls the configuration of the MetaDataRepository. The following are valid properties:

- `Preload`: A boolean property. If true, OpenJPA will eagerly load the repository on EntityManagerFactory creation. As a result, all Entity classes will be eagerly loaded by the JVM. Once MetaData preloading completes, all locking is removed from the MetaDataRepository and this will result in a much more scalable repository. If false, the repository will be lazily loaded as Entity classes are loaded by the JVM. The default value is false.

## Metadata Repository

Setting the Preload Property on Metadata Repository

    <property name="openjpa.MetaDataRepository" value="Preload=true"/>

## Additional JPA Metadata

This section describes OpenJPA's core additions to standard entity metadata. We present the object-relational mapping syntax to support these additions in . Finally, covers additional extensions to JPA metadata that allow you to access auxiliary OpenJPA features.

### Datastore Identity

JPA typically requires you to declare one or more `Id` fields to act as primary keys. OpenJPA, however, can create and maintain a surrogate primary key value when you do not declare any `Id` fields. This form of persistent identity is called datastore identity. discusses OpenJPA's support for datastore identity in JPA. We cover how to map your datastore identity primary key column in

identity datastore

### Surrogate Version

Just as OpenJPA can maintain your entity's identity without any `Id` fields, OpenJPA can maintain your entity's optimistic version without any `Version` fields. shows you how to map surrogate version columns.

version surrogate

### Persistent Field Values

JPA defines `Basic`, `Lob`, `Embedded` , `ManyToOne`, and `OneToOne` persistence strategies for direct field values. OpenJPA supports all of these standard strategies, but adds one of its own: `Persistent`. The org.apache.openjpa.persistence.Persistent metadata annotation can represent any direct field value, including custom types. It has the following properties:

- `FetchType fetch`: Whether to load the field eagerly or lazily. Corresponds exactly to the same-named property of standard JPA annotations such as Basic . Defaults to `FetchType.EAGER`.

- `CascadeType[] cascade`: Array of enum values defining cascade behavior for this field. Corresponds exactly to the same-named property of standard JPA annotations such as ManyToOne. Defaults to empty array.

- `String mappedBy`: Names the field in the related entity that maps this bidirectional relation. Corresponds to the same-named property of standard JPA annotations such as OneToOne.

- `boolean optional`: Whether the value can be null. Corresponds to the same-named property of standard JPA annotations such as ManyToOne , but can apply to non-entity object values as well. Defaults to `true`.

- `boolean embedded`: Set this property to `true` if the field value is stored as an embedded object.

Though you can use the Persistent annotation in place of most of the standard direct field annotations mentioned above, we recommend primarily using it for non-standard and custom types for which no standard JPA annotation exists. For example, demonstrates the use of the Persistent annotation to denote a persistent java.awt.Point field.

persistent fields

### Persistent Collection Fields

JPA standardizes support for collections of entities with the `OneToMany` and `ManyToMany` persistence strategies. OpenJPA supports these strategies, and may be extended for other strategies as well. For extended strategies, use the org.apache.openjpa.persistence.PersistentCollection metadata annotation to represents any persistent collection field. It has the following properties:

- `Class elementType`: The class of the collection elements. This information is usually taken from the parameterized collection element type. You must supply it explicitly, however, if your field isn't a parameterized type.

- `FetchType fetch`: Whether to load the collection eagerly or lazily. Corresponds exactly to the same-named property of standard JPA annotations such as Basic. Defaults to `FetchType.LAZY`.

- `String mappedBy`: Names the field in the related entity that maps this bidirectional relation. Corresponds to the same-named property of standard JPA annotations such as ManyToMany.

- `CascadeType[] elementCascade`: Array of enum values defining cascade behavior for the collection elements. Corresponds exactly to the `cascade` property of standard JPA annotations such as ManyToMany. Defaults to empty array.

- `boolean elementEmbedded`: Set this property to `true` if the elements are stored as embedded objects.

persistent fields collection metadata

### Persistent Map Fields

JPA has limited support for maps. If you extend JPA's standard map support to encompass new mappings, use the org.apache.openjpa.persistence.PersistentMap metadata annotation to represent your custom persistent map fields. It has the following properties:

- `Class keyType`: The class of the map keys. This information is usually taken from the parameterized map key type. You must supply it explicitly, however, if your field isn't a parameterized type.

- `Class elementType`: The class of the map values. This information is usually taken from the parameterized map value type. You must supply it explicitly, however, if your field isn't a parameterized type.

- `FetchType fetch`: Whether to load the collection eagerly or lazily. Corresponds exactly to the same-named property of standard JPA annotations such as Basic. Defaults to `FetchType.LAZY`.

- `CascadeType[] keyCascade`: Array of enum values defining cascade behavior for the map keys. Corresponds exactly to the `cascade` property of standard JPA annotations such as ManyToOne. Defaults to empty array.

- `CascadeType[] elementCascade`: Array of enum values defining cascade behavior for the map values. Corresponds exactly to the `cascade` property of standard JPA annotations such as ManyToOne. Defaults to empty array.

- `boolean keyEmbedded`: Set this property to `true` if the map keys are stored as embedded objects.

- `boolean elementEmbedded`: Set this property to `true` if the map values are stored as embedded objects.

persistent fields map metadata
metadata JPA additions

## Metadata Extensions

OpenJPA extends standard metadata to allow you to access advanced OpenJPA functionality. This section covers persistence metadata extensions; we discuss mapping metadata extensions in . All metadata extensions are optional; OpenJPA will rely on its defaults when no explicit data is provided.

### Class Extensions

OpenJPA recognizes the following class extensions:

#### Fetch Groups

The org.apache.openjpa.persistence.FetchGroups and org.apache.openjpa.persistence.FetchGroup annotations allow you to define fetch groups in your JPA entities. discusses OpenJPA's support for fetch groups in general; see for how to use these annotations in particular.

metadata extensions fetch groups fetch groups

#### Data Cache

examines caching in OpenJPA. Metadata extensions allow individual classes to override system caching defaults.

OpenJPA defines the org.apache.openjpa.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.

- `int timeout`: The number of milliseconds data for the class remains valid. Use -1 for no timeout. Defaults to the `openjpa.DataCacheTimeout` property value.

metadata extensions data cache caching

#### Detached State

The OpenJPA enhancer may add a synthetic field to detachable classes to hold detached state (see for details). You can instead declare your own detached state field or suppress 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.

OpenJPA defines the org.apache.openjpa.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.

metadata extensions detached state field detachment

### Field Extensions

OpenJPA recognizes the following field extensions:

#### Dependent

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. (This latter processing is analogous to using JPA's CascadeType.REMOVE functionality as described in .) You can prevent an orphaned dependent object from being automatically deleted by assigning it to another relation in the same transaction.

OpenJPA offers a family of marker annotations to denote dependent relations in JPA entities:

- org.apache.openjpa.persistence.Dependent: Marks a direct relation as dependent.

- org.apache.openjpa.persistence.ElementDependent : Marks the entity elements of a collection, array, or map field as dependent.

- org.apache.openjpa.persistence.KeyDependent: Marks the key entities in a map field as dependent.

metadata extensions dependent

#### Load Fetch Group

The org.apache.openjpa.persistence.LoadFetchGroup annotation specifies a field's load fetch group. discusses OpenJPA's support for fetch groups in general; see for how to use this annotation in particular.

metadata extensions load fetch group
fetch groups load fetch group

#### LRS

This boolean extension, denoted by the OpenJPA org.apache.openjpa.persistence.LRS annotation, indicates that a field should use OpenJPA's special large result set collection or map proxies. A complete description of large result set proxies is available in .

metadata extensions lrs large result sets

#### Inverse-Logical

This extension names the inverse field in a logical bidirectional relation. To create a logical bidirectional relation in OpenJPA, use the org.apache.openjpa.persistence.InverseLogical annotation. We discuss logical bidirectional relations and this extension in detail in .

metadata extensions inverse-logical bidirectional relations

#### Read-Only

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 org.apache.openjpa.persistence.ReadOnly annotation to an org.apache.openjpa.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 OpenJPA data cache.

- `UpdateAction.RESTRICT`: Any attempt to change the field will result in an immediate exception.

metadata extensions read-only persistent fields
persistent fields read only

#### Type

OpenJPA has three levels of support for relations:

1. 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.

2. 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.

3. 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, OpenJPA uses level 1 support. By default, OpenJPA 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, OpenJPA lumps it together with java.lang.Object fields and other non-interface, unrecognized field types, which are all assigned level 3 support.

With OpenJPA'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 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 OpenJPA assumes interface fields will always hold persistent instances by default).

This extension is also used with OpenJPA's externalization feature, described in .

OpenJPA defines the following type annotations for field values, collection, array, and map elements, and map keys, respectively:

- org.apache.openjpa.persistence.Type

- org.apache.openjpa.persistence.ElementType

- org.apache.openjpa.persistence.KeyType

metadata extensions type persistent fields

#### Externalizer

The OpenJPA org.apache.openjpa.persistence.Externalizer annotation names a method to transform a field value into a value of another type. See for details.

metadata extensions externalizer externalization

#### Factory

The OpenJPA org.apache.openjpa.persistence.Factory annotation names a method to re-create a field value from its externalized form. See for details.

metadata extensions factory externalization

#### External Values

The OpenJPA org.apache.openjpa.persistence.ExternalValues annotation declares values for transformation of simple fields to different constant values in the datastore. See for details.

metadata extensions external values externalization

### Example

The following example shows you how to specify extensions in metadata.

OpenJPA Metadata Extensions

    import org.apache.openjpa.persistence.*;

    @Entity
    @DataCache(enabled=false)
    public class Magazine
    {
        @ManyToMany
        @LRS
        private Collection<Subscriber> subscribers;

        @ExternalValues({"true=1", "false=2"})
        @Type(int.class)
        private boolean weekly;

        ...
    }

### XML extensions

OpenJPA has extended the JPA 2.0 schema to include elements and attributes corresponding to OpenJPA extended metadata and mapping annotations. The schema are contained in 2 files: extendable-orm.xsd and openjpa-orm.xsd. The extendable-orm.xsd file provides copies of some of the JPA 2.0 schema elements with additional schema to make it extendable. The openjpa-orm.xsd file extends the extendable-orm.xsd with OpenJPA specific elements and attributes representing OpenJPA annotations. Currently, only a subset of annotations have actually been implemented, and some of those have been partially tested. The current status can be found by comments in the openjpa-orm.xsd schema file.

In order to use the OpenJPA extensions in your mapping file you must include the namespaces for these 2 new schemas as well as for the schema for JPA 2.0, as shown in the following example:

OpenJPA Schema Extensions

    <entity-mappings xmlns="http://www.apache.org/openjpa/ns/orm/extendable"
        xmlns:openjpa="http://www.apache.org/openjpa/ns/orm"
        xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        version="2.0">

        <entity class="org.apache.openjpa.persistence.jdbc.annotations.MultiColumnVersionPC"
            metadata-complete="true">
            <table name="MCV"/>
            <attributes>
                <id name="id">
                    <orm:generated-value/>
                </id>
                <basic name="id"/>
                <basic name="name"/>
            </attributes>
            <openjpa:entity version-strategy="version-numbers">
                <openjpa:version-columns>
                    <openjpa:version-column name="v1"/>
                    <openjpa:version-column name="v2"/>
                    <openjpa:version-column name="v3"
                        column-definition="FLOAT"
                        scale="3"
                        precision="10"/>
                </openjpa:version-columns>
            </openjpa:entity>
        </entity>

    </entity-mappings>

metadata extensions