Jump to: navigation, search

EclipseLink/Development/1.0/ER-200040 DS M4

< EclipseLink‎ | Development
Revision as of 10:35, 28 February 2008 by Guy.pelletier.oracle.com (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This design document is for ER200040: New native XML metadata format. NOTE The items discussed in this documented are to be implemented and tested for Milestone 4.

Contents

Design Specification: JPA XML metadata extensions

Document History

Date Author Version Description
2007-09-25 Guy Pelletier Initial Draft
2007-09-26 James Sutherland Added Comments
2007-10-10 Guy Pelletier Second Draft

Goals

The goal of this design spec is to expose some features from EclipseLink that are currently not available through the use of JPA xml metadata. The features that will be exposed in this document already have their annotation counterparts implemented in the current version of EclipseLink. This document assumes familiarity with those annotations and will focus mainly on the XML extension portions. That is, in most cases, internal processing and design remains as already defined for the equivalent annotations. This document will discuss only those portions that will be required to be implemented or addressed as a result of introducing the new xml elements.

The new xml configurations will be added to the eclipse_orm_1_0.xsd file. This file will be a copy of the latest JPA orm.xml file plus the newly created xml elements.

Also note, the new features exposed by this design spec are by no means the end all of features available from EclipseLink. It is merely a set that collectively has been agreed upon as most important to expose in this release. The ultimate goal remains to completely replace the existing EclipseLink deployment project with the configuration of annotations and/or XML.

NOTE The items discussed in this documented are to be implemented and tested for Milestone 2. Those items in the Future enhancements or investigations section will be addressed in a later Milestones.

ORM file

The new orm file (eclipse_orm_1_0.xsd) will need to be hosted somewhere. Where?

  <entity-mappings version="1.0" xmlns="http://????? " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://????? eclipse_orm_1_0.xsd">

Package

  • New classes will be added to their respectful metadata directory under the xml package. E.G. XML converter metadata classes should be added under the org.eclipse.persistence.internal.jpa.metadata.converters.xml. This will be outlined with each new xml element discussed in this document.

Converters

The following converter complex types will be added (converter, type-converter, object-type-converter, struct-converter) and there usage is specified through the convert attribute on those mapping elements that support using a converter. The following converter elements,

  <xsd:element name="converter" type="orm:converter" minOccurs="0" maxOccurs="unbounded"/>
  <xsd:element name="type-converter" type="orm:type-converter" minOccurs="0" maxOccurs="unbounded"/>
  <xsd:element name="object-type-converter" type="orm:object-type-converter" minOccurs="0" maxOccurs="unbounded"/>
  <xsd:element name="struct-converter" type="orm:struct-converter" minOccurs="0" maxOccurs="unbounded"/>

will be available from the following complex-types:

  • entity-mappings
  • entity
  • embeddable
  • mapped-superclass

The new convert element,

  <xsd:element name="convert" type="xsd:string"/>

will be added to the following complex types:

  • basic
  • basic-map
  • basic-collection
  • id
  • version

converter

The converter complex type will be added and is used to specify a custom converter for modification of the data value(s) during the reading and writing of a mapped attribute.

  <xsd:complexType name="converter">
    <xsd:annotation>
      <xsd:documentation>

        @Target({TYPE, METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface Converter {
          /**
           * (Required) Name this converter. The name should be unique
           * across the whole persistence unit.
           */
          String name();

          /**
           * (Required) The converter class to be used. This class must implement 
           * the org.eclipse.persistence.mappings.converters.Converter interface.
           */
          Class converterClass(); 
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="name" type="xsd:string" use="required"/>
    <xsd:attribute name="converter-class" type="xsd:string" use="required"/>
  </xsd:complexType>

Example

  <converter name="gender" converter-class="my.gender.converter"/>

Design and processing

  • XML metadata mapped though OX to the existing class: org.eclipse.persistence.internal.jpa.metadata.converters.ConverterMetadata.

type-converter

The type-converter complex type will be added and is used to specify an org.eclipse.persistence.mappings.converters.TypeConversionConverter for modification of the data value(s) during the reading and writing of a mapped attribute

  <xsd:complexType name="type-converter">
    <xsd:annotation>
      <xsd:documentation>

        @Target({TYPE, METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface TypeConverter {
          /**
           * (Required) Name this converter. The name should be unique
           * across the whole persistence unit.
           */
           String name();

          /**
           * (Optional) Specify the type stored on the database. The
           * default is inferred from the type of the persistence field 
           * or property.
           */
          Class dataType() default void.class;

          /**
           * (Optional) Specify the type stored on the entity. The
           * default is inferred from the type of the persistent field 
           * or property.
           */
          Class objectType() default void.class;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="name" type="xsd:string" use="required"/>
    <xsd:attribute name="data-type" type="xsd:string"/>
    <xsd:attribute name="object-type" type="xsd:string"/>
  </xsd:complexType>

Example

  <type-converter name="doubleToFloat" data-type="java.lang.Double" object-type="java.lang.Float"/>

Design and processing

  • XML metadata mapped though OX to the existing class:

org.eclipse.persistence.internal.jpa.metadata.converters.TypeConverterMetadata.

object-type-converter

The object-type-converter complex type (extends the type-converter complex type) will be added and is used to specify an org.eclipse.persistence.mappings.converters.ObjectTypeConverter that converts a fixed number of database data value(s) to Java object value(s) during the reading and writing of a mapped attribute.

  <xsd:complexType name="object-type-converter">
    <xsd:complexContent>	
      <xsd:extension base=type-converter>
        <xsd:annotation>
          <xsd:documentation>

            @Target({TYPE, METHOD, FIELD})
            @Retention(RUNTIME)
            public @interface ObjectTypeConverter {
              /**
               * (Required) Name this converter. The name should be unique
               * across the whole persistence unit.
               */
              String name();

              /**
               * (Optional) Specify the type stored on the database. The
               * default is inferred from the type of the persistence
               * field or property.
               */
              Class dataType() default void.class;

              /**
               * (Optional) Specify the type stored on the entity. The
               * default is inferred from the type of the persistent 
               * field or property.
               */
              Class objectType() default void.class;

              /**
               * (Required) Specify the conversion values to be used 
               * with the object converter.
               */
              ConversionValue[] conversionValues();

              /**
               * (Optional) Specify a default object value. Used for 
               * legacy data if the data value is missing.
               */
              String defaultObjectValue() default "";
            }

          </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
          <xsd:element name="conversion-value" type="orm:conversion-value" minOccurs="1" maxOccurs=unbounded/>
          <xsd:element name="default-object-value" type="xsd:string" minOccurs="0"/>
        </xsd:sequence>
      </xsd:entension>
    </xsd:complexContent>
  </xsd:complexType>

conversion-value

The conversion-value complex type will be added and is used within an object-type-converter. It is used to specify data and Java object conversion values(s).

  <xsd:complexType name="conversion-value">
    <xsd:annotation>
      <xsd:documentation>

        @Target({})
        @Retention(RUNTIME)
        public @interface ConversionValue {
          /**
           * (Required) Specify the database value.
           */
          String dataValue();

          /**
           * (Required) Specify the object value.
           */
          String objectValue();
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="data-value" type="xsd:string"/>
    <xsd:attribute name="object-value" type="xsd:string"/>
  </xsd:complexType>

Example

  <object-type-converter name="sexConverter" data-type="java.lang.String" object-type="java.lang.String">
    <conversion-value data-value="F" object-value="Female"/>
    <conversion-value data-value="M" object-value="Male"/>
  </object-type-converter>

Design and processing

  • XML metadata mapped though OX to the existing class:

org.eclipse.persistence.internal.jpa.metadata.converters.ObjectTypeConverterMetadata.

  • Note: The processing allows multiple data-value for the same object-value, the first one is processed normally, and additional data-values are added as one-way conversions.

struct-converter

The struct-converter complex type will be added and is used to specify a spatial converter. Currently, internally only the JGeometry spatial type is supported (unless the user builds their own) and it maps to a org.eclipse.persistence.platform.database.oracle.converters.JGeometryConverter which converts the JGeometry values as they are read and written from the database.

  <xsd:complexType name="struct-converter">
    <xsd:annotation>
      <xsd:documentation>

        @Target({TYPE, METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface StructConverter {
          /**
           * (Required) Name this converter. The name should be unique across the 
           * whole persistence unit.
           */
          String name();

          /**
           * (Required) The converter class to be used. This class must implement the
           * EclipseLink org.eclipse.persistence.mappings.converters.Converter interface.
           */
          String converter(); 
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="name" type="xsd:string" use="required">
    <xsd:attribute name="converter" type="xsd:string" use="required"/>
  </xsd:complexType>

Example

  <struct-converter name="JGeometry" converter="JGEOMETRY"/>

Design and processing

  • XML metadata mapped though OX to the existing class:

org.eclipse.persistence.internal.jpa.metadata.converters.StructConverterMetadata.

Mapping Annotations

The following new mapping related elements will be added (and they will be available from the attributes complex element).

  1. basic-collection
  2. basic-map
  3. collection-table

collection-table

A collection-table is used in conjunction with a basic-collection or a basic-map element. If no collection-table is defined with a basic-collection or basic-map then one will be defaulted. (see comment on name() below)

The following collection-table complex type will be added. See the basic-collection and basic-map elements for more information.

  <xsd:complexType name="collection-table">
    <xsd:annotation>
      <xsd:documentation>

        @Target({METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface CollectionTable {
          /**
           * (Optional) The name of the collection table. If it is not specified, it is defaulted to the
           * concatenation of the following: the name of the source entity; "_" ; the name of the 
           * relationship property or field of the source entity.
           */
          String name() default ""; 

          /**
           * (Optional) The catalog of the table. It defaults to the persistence unit default catalog.
           */
          String catalog() default ""; 

          /**
           * (Optional) The schema of the table. It defaults to the persistence unit default schema.
           */
          String schema() default ""; 

          /**
           * (Optional) Used to specify a primary key column that is used as a foreign key to join to
           * another table. If the source entity uses a composite primary key, a primary key join column 
           * must be specified for each field of the composite primary key. In a single primary key case, 
           * a primary key join column may optionally be specified. Defaulting will apply otherwise as 
           * follows:
           * name, the same name as the primary key column of the primary table of the source entity.
           * referencedColumnName, the same name of primary key column of the primary table of the source 
           * entity.
           */
          PrimaryKeyJoinColumn[] primaryKeyJoinColumns() default {}; 
 
          /**
           * (Optional) Unique constraints that are to be placed on the table. These are only
           * used if table generation is in effect.
           */
          UniqueConstraint[] uniqueConstraints() default {}; 
       }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="primary-key-join-column" type="orm:primary-key-join-column" minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="unique-constraint" type="orm:unique-constraint" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="catalog" type="xsd:string"/>
    <xsd:attribute name="schema" type="xsd:string"/>
  </xsd:complexType>

Example

See basic-map example or basic-collection example.

Design and processing

  • XML metadata mapped though OX to the existing class:

org.eclipse.persistence.internal.jpa.metadata.tables.CollectionTableMetadata.

  • Processing of the collection-table will be performed when processing a basic-collection or basic-map.
  • For more processing details see org.eclipse.persistence.internal.jpa.metadata.accessors.BasicCollectionAccessor and org.eclipse.persistence.internal.jpa.metadata.accessors.BasicMapAccessor

basic-collection

The basic-collection element is used to map an org.eclipse.persistence.mappings.DirectCollectionMapping which stores a collection of simple types (String, Number, Date, etc.) into a single table. The table must store the value and a foreign key to the source object. A basic-collection is used in conjunction with a collection-table and/or convert if necessary. Note, a basic-collection may also be marked as private-owned.

  <xsd:complexType name="basic-collection">
    <xsd:annotation>
      <xsd:documentation>

        @Target({METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface BasicCollection {
          /**
           * (Optional) Defines whether the value of the field or property 
           * should be lazily loaded or must be eagerly fetched. The EAGER 
           * strategy is a requirement on the persistence provider runtime that 
           * the value must be eagerly fetched. The LAZY strategy is a hint to 
           * the persistence provider runtime. If not specified, defaults to 
           * LAZY.
           */
          FetchType fetch() default LAZY; 
 
          /**
           * (Optional) The name of the value column that holds the direct 
           * collection data. Defaults to the property or field name.
           */
          Column valueColumn() default @Column;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="value-column" type="orm:column" minOccurs="0"/>
      <xsd:element name="convert" type="xsd:string"/>
      <xsd:element name="collection-table" type="orm:collection-table" minOccurs="0"/>
      <xsd:element name="private-owned" type="orm:emptyType"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="fetch" type="orm:fetch-type"/>
    <xsd:attribute name="join-fetch" type="orm:join-fetch-type"/>
  </xsd:complexType>

Example

  <basic-collection fetch="LAZY" join-fetch="INNER">
    <value-column name="DESCRIPTION"/>
    <collection-table name="RESPONSIBILITIES">
      <primary-key-join-column name="EMPLOYEE_ID" referenced-column-name="EMP_ID">
    </collection-table>
    <private-owned/>
  </basic-collection>

Design and processing

  • XML metadata mapped though OX to the existing class:

org.eclipse.persistence.internal.jpa.metadata.accessors.BasicCollectionAccessor.

  • For internal processing details see BasicCollectionAccessor.
  • If a basic-collection is specified on an attribute of type Map, an exception will be thrown. This will need to be handled in XMLClassAccessor (when building an XMLBasicCollectionAccessor)

basic-map

The basic-map xml element is used to map a oracle.toplink.mappings.BasicMapMapping which stores a collection of key-value pairs. The key and value must be simple types (String, Number, Date, etc.) and stored in a single table along with a foreing key to the source object. A basic-map can be used in conjunction with a collection-table. Note, a basic-map may also be marked as private-owned.

  <xsd:complexType name="basic-map">
    <xsd:annotation>
      <xsd:documentation>

        @Target({METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface BasicMap {
          /**
           * (Optional) Defines whether the value of the field or property 
           * should be lazily loaded or must be eagerly fetched. The EAGER 
           * strategy is a requirement on the persistence provider runtime that 
           * the value must be eagerly fetched. The LAZY strategy is a hint to 
           * the persistence provider runtime. If not specified, defaults to 
           * LAZY.
           */
          FetchType fetch() default LAZY;

          /**
           * (Optional) The name of the data column that holds the direct map 
           * key. If the name on te key column is "", the name will default to:
           * the name of the property or field; "_key".
           */
          Column keyColumn();

          /**
           * (Optional) Specify the key converter. Default is equivalent to 
           * specifying @Convert("none"), meaning no converter will be added to 
           * the direct map key.
           */
          Convert keyConverter() default @Convert;

          /**
           * (Optional) The name of the data column that holds the direct 
           * collection data. Defaults to the property or field name.
           */
          Column valueColumn() default @Column;

          /**
           * (Optional) Specify the value converter. Default is equivalent to 
           * specifying @Convert("none"), meaning no converter will be added to 
           * the value column mapping.
           */
          Convert valueConverter() default @Convert;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="key-column" type="orm:column" minOccurs="0"/>
      <xsd:element name="key-converter" type="xsd:string"/>    
      <xsd:element name="value-column" type="orm:column" minOccurs="0"/>
      <xsd:element name="value-converter" type="xsd:string"/>    
      <xsd:element name="collection-table" type="orm:collection-table" minOccurs="0"/>
      <xsd:element name="private-owned" type="orm:emptyType"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="fetch" type="orm:fetch-type"/>
    <xsd:attribute name="join-fetch" type="orm:join-fetch-type"/>
  </xsd:complexType>

Example

  <basic-map fetch="LAZY" private-owned="false" join-fetch="OUTER">
    <key-column name="LICENSE"/>
    <key-converter>licenseConverter</key-converter>
    <value-column name="STATUS"/>
    <value-converter>Integer2String</value-converter>
    <collection-table name="LICENSES">
      <primary-key-join-column name="RESTAURANT_ID" referenced-column-name="ID">
    </collection-table>
  </basic-map>

Design and processing

  • XML metadata mapped though OX to the existing class: org.eclipse.persistence.internal.jpa.metadata.accessors.BasicMapAccessor.
  • For internal processing details see BasicMapAccessor and BasicCollectionAccessor.
  • If a basic-map is specified on an attribute of type Map, an exception will be thrown.

private-owned

The private-owned element,

  <xsd:element name="private-owned" type="xsd:boolean"/>

used to mark a mapping as privately owned on the given entity, will be supported on the following complex types:

  • one-to-one
  • one-to-many
  • basic-collection
  • basic-map.

Example

  <one-to-many name="phoneNumbers" target-entity="my.PhoneNumber" mapped-by="owner" private-owned="true">
    ....
  </one-to-many>

  <one-to-one name="manager" target-entity="my.Employee" private=owned="false">
    ....
  </one-to-many>

See basic-collection and basic-map for more examples.

Design and processing

  • XML metadata mapped though OX to the existing class that support a private owned specification. OneToMany, OneToOne, BasicCollection and BasicMap.
  • Current processing error when using a 1-M with a join-table. Privately-owned is currently not being processed. This will be corrected.

Optimistic Locking

The 5 supported locking policies were previously supported through the usage of an @OptimisticLocking annotation. The supported EclipseLink policies are:

  • org.eclipse.persistence.descriptors.AllFieldsLockingPolicy
  • org.eclipse.persistence.descriptors.ChangedFieldsLockingPolicy
  • org.eclipse.persistence.descriptors.SelectedFieldsLockingPolicy
  • org.eclipse.persistence.descriptors.VersionLockingPolicy
  • org.eclipse.persistence.descriptors.TimestampLockingPolicy

optimistic-locking

The optimistic-locking complex type will be added is used to specify the type of optimistic locking ExclipseLink should use when updating or deleting entities.

The optimistic-locking element,

  <xsd:element name="optimistic-locking" type="orm:optimistic-locking" minOccurs="0"/>

will be supported on the following complex types:

  • entity
  • mapped-superclass
  <xsd:complexType name="optimistic-locking">
    <xsd:annotation>
      <xsd:documentation>

       @Target({TYPE})
       @Retention(RUNTIME)
       public @interface OptimisticLocking {
         /**
          * (Optional) The type of optimistic locking policy to use.
          */
         OptimisticLockingType type() default VERSION_COLUMN;

         /**
          * (Optional) For an optimistic locking policy of type SELECTED_COLUMNS, this annotation
          * member becomes a (Required) field.
          */
         Column[] selectedColumns() default {};

         /**
          * (Optional) Specify where the optimistic locking policy should cascade lock. Currently
          * only supported with VERSION_COLUMN locking.
          */
         boolean cascade() default false;
       }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="selected-column" type="orm:column" minOccurs="0" maxOccours="unbounded"/>    
    </xsd:sequence>
    <xsd:attribute name="type" type="orm:optimisitic-locking-type"/>
    <xsd:attribute name="cascade" type="xsd:boolean"/>
  </xsd:complexType>

optimistic-locking-type

The optimistic-locking-type simple type will be added and is used in conjunction with the optimistic-locking complex type.

  <xsd:simpleType name="optimistic-locking-type">
    <xsd:annotation>
      <xsd:documentation>

        public enum OptimisticLockingType {
          /**
           * Using this type of locking policy compares every field in the table
           * in the WHERE clause when doing an update or a delete. If any field
           * has been changed, an optimistic locking exception will be thrown.
           */
          ALL_COLUMNS,

          /**
           * Using this type of locking policy compares only the changed fields
           * in the WHERE clause when doing an update. If any field has been
           * changed, an optimistic locking exception will be thrown. A delete
           * will only compare the primary key.
           */
          CHANGED_COLUMNS,

          /**
           * Using this type of locking compares selected fields in the WHERE
           * clause when doing an update or a delete. If any field has been
           * changed, an optimistic locking exception will be thrown. Note that
           * the fields specified must be mapped and not be primary keys.
           */
          SELECTED_COLUMNS,

          /**
           * Using this type of locking policy compares a single version number
           * in the where clause when doing an update. The version field must be
           * mapped and not be the primary key.
           */
          VERSION_COLUMN
        }

      </xsd:annotation>
    </xsd:documentation>
    <xsd:restriction base="xsd:token">
      <xsd:enumeration value="ALL_COLUMNS"/>
      <xsd:enumeration value="CHANGED_COLUMNS"/>
      <xsd:enumeration value="SELECTED_COLUMNS"/>
      <xsd:enumeration value="VERSION_COLUMN"/>
    </xsd:restriction>
  </xsd:simpleType>

Setting an optimistic-locking on an entity 'could' override any version specification found on an attribute for the given entity. No exception is thrown, instead a warning message will be logged. Since version was introduced by JPA, a version element without an optimistic-locking element is still a valid way to define a VersionLockingPolicy on the source entity.

Example

  <entity name="Employee" class="my.Employee" access="PROPERTY" change-tracking="DEFERRED">
  
    ....

    <optimistic-locking type="SELECTED_COLUMNS" cascade="false">
      <selected-column name="id"/>
      <selected-column name="firstName"/>
    </optimistic-locking>

    ....

  </entity>

Design and processing

  • Build new org.eclipse.persistence.internal.jpa.metadata.optimisticlocking.xml.XMLOptimisticLocking that extends org.eclipse.persistence.internal.jpa.metadata.optimisticlocking.MetadataOptimisticLocking. Its sole purpose will be to override the metatada values processed for the optimistic locking policy.
  • org.eclipse.persistence.internal.jpa.metadata.accessors.xml.XMLClassAccessor will be responsible for building the XMLOptimisticLocking.

Entity Caching

EclipseLink uses identity maps to cache objects for performance and maintain object identity. Users can control the cache and its behavior by specifying the cache element on their entity classes.

cache

The cache complex type will be created and is used to specify the caching strategy for a given entity. In the case of inheritance, a cache element can only be defined on the root of the inheritance hierarchy. The cache complex type will make use of two new simple types as well, cache-type and cache-coordination-type.

The cache element,

  <xsd:element name="cache" type="orm:cache" minOccurs="0"/>

will be supported on the following complex types:

  • entity
  • mapped-superclass
  <xsd:complexType name="cache">
    <xsd:annotation>
      <xsd:documentation>
        
        @Target({TYPE})
        @Retention(RUNTIME)
        public @interface Cache {
          /**
           * (Optional) The type of cache to use.
           */ 
          CacheType type() default SOFT_WEAK;

          /**
           * (Optional) The size of cache to use.
           */ 
          int size() default 100;

          /**
           * (Optional) Cached instances in the shared cache or a client isolated cache.
           */ 
          boolean isolated() default false;

          /**
           * (Optional) Expire cached instance after a fix period of time (ms). 
           * Queries executed against the cache after this will be forced back 
           * to the database for a refreshed copy
           */ 
          int expiry() default -1; // minus one is no expiry.

          /**
           * (Optional) Expire cached instance a specific time of day. Queries 
           * executed against the cache after this will be forced back to the 
           * database for a refreshed copy
           */ 
          TimeOfDay expiryTimeOfDay() default @TimeOfDay(specified=false);

          /**
           * (Optional) Force all queries that go to the database to always 
           * refresh the cache.
           */ 
          boolean alwaysRefresh() default false;

          /**
           * (Optional) For all queries that go to the database, refresh the cache 
           * only if the data received from the database by a query is newer than 
           * the data in the cache (as determined by the optimistic locking field)
           */ 
          boolean refreshOnlyIfNewer() default false;

          /**
           * (Optional) Setting to true will force all queries to bypass the 
           * cache for hits but still resolve against the cache for identity. 
           * This forces all queries to hit the database.
           */ 
          boolean disableHits() default false;

          /**
           * (Optional) The cache coordination mode.
           */ 
          CacheCoordinationType coordinationType() default SEND_OBJECT_CHANGES;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:choice>
      <xsd:element name="expiry" type="xsd:integer" minOccurs=0/>
      <xsd:element name="expiry-time-of-day" type="orm:time-of-day" minOccurs=0/>
    </xsd:choice>
    <xsd:attribute name="size" type="xsd:integer"/>
    <xsd:attribute name="isolated" type="xsd:boolean"/>
    <xsd:attribute name="type" type="orm:cache-type"/>
    <xsd:attribute name="always-refresh" type="xsd:boolean"/>
    <xsd:attribute name="refresh-only-if-newer" type="xsd:boolean"/>
    <xsd:attribute name="disable-hits" type="xsd:boolean"/>
    <xsd:attribute name="coordination-type" type="orm:cache-coordination-type"/>
  </xsd:complexType>

cache-type

The cache-type simple type is used within the cache complex type.

  <xsd:simpleType name="cache-type">
    <xsd:annotation>
      <xsd:documentation>

        public enum CacheType {
          /**
           * Provides full caching and guaranteed identity. Caches all objects
           * and does not remove them. 
           * WARNING: This method may be memory intensive when many objects are 
           * read.
           */
          FULL,

          /**
           * Similar to the FULL identity map except that the map holds the
           * objects using weak references. This method allows full garbage
           * collection and provides full caching and guaranteed identity.
           */
          WEAK,

          /**
           * Similar to the FULL identity map except that the map holds the
           * objects using soft references. This method allows full garbage
           * collection when memory is low and provides full caching and guaranteed identity.
           */
          SOFT,

          /**
           * Similar to the WEAK identity map except that it maintains a
           * most-frequently-used sub-cache. The size of the sub-cache is
           * proportional to the size of the identity map as specified by
           * descriptor's setIdentityMapSize() method. The sub-cache
           * uses soft references to ensure that these objects are
           * garbage-collected only if the system is low on memory.
           */
          SOFT_WEAK,

          /**
           * Identical to the soft cache weak (SOFT_WEAK) identity map except 
           * that it uses hard references in the sub-cache. Use this identity 
           * map if soft references do not behave properly on your platform.
           */
          HARD_WEAK,

          /**
           * A cache identity map maintains a fixed number of objects
           * specified by the application. Objects are removed from the cache
           * on a least-recently-used basis. This method allows object
           * identity for the most commonly used objects.
           * WARNING: Furnishes caching and identity, but does not guarantee 
           * identity.
           */
          CACHE,

          /**
           * WARNING: Does not preserve object identity and does not cache 
           * objects.
           */
          NONE
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:token">
      <xsd:enumeration value="FULL"/>
      <xsd:enumeration value="WEAK"/>
      <xsd:enumeration value="SOFT"/>
      <xsd:enumeration value="SOFT_WEAK"/>
      <xsd:enumeration value="HARD_WEAK"/>
      <xsd:enumeration value="CACHE"/>
      <xsd:enumeration value="NONE"/>
    </xsd:restriction>
  </xsd:simpleType>

cache-coordination-type

The cache-coordination-type simple type is used within the cache complex type.

  <xsd:simpleType name="cache-coordination-type">
    <xsd:annotation>
      <xsd:documentation>

          public enum CacheCoordinationType {
          /**
           * Sends a list of changed objects including data about the changes. This data is merged into 
           * the receiving cache.
           */
          SEND_OBJECT_CHANGES,

          /**
           * Sends a list of the identities of the objects that have changed. The receiving cache 
           * invalidates the objects (rather than changing any of the data)
           */
          INVALIDATE_CHANGED_OBJECTS,

          /**
           * Same as SEND_OBJECT_CHANGES except it also includes any newly created objects from the 
           * transaction.
           */
          SEND_NEW_OBJECTS_WITH_CHANGES,

          /**
           * Does no cache coordination.
           */
          NONE
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:token">
      <xsd:enumeration value="SEND_OBJECT_CHANGES"/>
      <xsd:enumeration value="INVALIDATE_CHANGED_OBJECTS"/>
      <xsd:enumeration value="SEND_NEW_OBJECTS_WITH_CHANGES"/>
      <xsd:enumeration value="NONE"/>
    </xsd:restriction>
  </xsd:simpleType>

time-of-day

A time-of-day complex type is used to specify a specific time of day using a Calendar instance. It is used used within the cache complex type.

  <xsd:complexType name="time-of-day">
    <xsd:annotation>
      <xsd:documentation>
        
        @Target({})
        @Retention(RUNTIME)
        public @interface TimeOfDay {
          /**
           * (Optional) Hour of the day.
           */ 
          int hour() default 0;

          /**
           * (Optional) Minute of the day.
           */ 
          int minute() default 0;

          /**
           * (Optional) Second of the day.
           */ 
          int second() default 0;

          /**
           * (Optional) Millisecond of the day.
           */ 
          int millisecond() default 0;

          /**
           * Internal use. Do not modify.
           */ 
          boolean specified() default true;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="hour" type="xsd:integer"/>
    <xsd:attribute name="minute" type="xsd:integer"/>
    <xsd:attribute name="second" type="xsd:integer"/>
    <xsd:attribute name="millisecond" type="xsd:integer"/>
  </xsd:complexType>

Example

  <cache type="FULL" isolated="false" always-refresh="true" refresh-only-if-newer="true" disable-hits="true" coordination-type="INVALIDATE_CHANGED_OBJECTS>

    ....

    <expiry>1000</expiry>
    or
    <expiry-time-of-day hour="0" minute="1" second="10" millisecond="3"/>

    ....

  </cache>

Design and processing

  • org.eclipse.peristence.internal.jpa.metadata.accessors.xml.XMLClassAccessor will need to override the necessary methods from org.eclipse.persistence.internal.jpa.metadata.accessors.ClassAccessor to ensure the xml metadata is processed.

Change Tracking

Change tracking is used to specify the org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy which computes changes sets for EclipseLink's UnitOfWork commit process. An ObjectChangePolicy is stored on an Entity's descriptor.

change-tracking

The change-tracking complex type will be created and the change-tracking element,

  <xsd:element name="change-tracking" type="orm:change-tracking"/>

will be supported on the following complex types:

  • entity
  • embeddable
  • mapped-superclass
  <xsd:complexType name="change-tracking">
    <xsd:annotation>
      <xsd:documentation>

        @Target({TYPE})
        @Retention(RUNTIME)
        public @interface ChangeTracking {
          /**
           * (Optional) The type of change tracking to use.
           */ 
          ChangeTrackingType value() default AUTO;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="type" type="orm:change-tracking-type" use="required"/>
  </xsd:complexType>

change-tracking-type

  <xsd:simpleType name="change-tracking-type">
    <xsd:annotation>
      <xsd:documentation>

        public enum ChangeTrackingType {
          /**
           * An ATTRIBUTE change tracking type allows change tracking at the attribute 
           * level of an object. Objects with changed attributes will be processed in 
           * the commit process to include any changes in the results of the commit.
           * Unchanged objects will be ignored.
           */
          ATTRIBUTE,

          /**
           * An OBJECT change tracking policy allows an object to calculate for itself 
           * whether it has changed. Changed objects will be processed in the commit 
           * process to include any changes in the results of the commit.
           * Unchanged objects will be ignored.
           */
          OBJECT,

          /**
           * A DEFERRED change tracking policy defers all change detection to the 
           * UnitOfWork's change detection process. Essentially, the calculateChanges() 
           * method will run for all objects in a UnitOfWork. 
           * This is the default ObjectChangePolicy
           */
          DEFERRED,

          /**
           * Will not set any change tracking policy.
           */
          AUTO
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:token">
      <xsd:enumeration value="ATTRIBUTE"/>
      <xsd:enumeration value="OBJECT"/>
      <xsd:enumeration value="DEFERRED"/>
      <xsd:enumeration value="AUTO"/>
    </xsd:restriction>
  </xsd:simpleType>

Example

  <entity name="Employee" class="my.Employee" access="PROPERTY">
    ....
    <change-tracking type="DEFERRED">
    ....
  </entity>

Design and processing

  • org.eclipse.peristence.internal.jpa.metadata.accessors.xml.XMLClassAccessor will need to override the necessary methods from org.eclipse.persistence.internal.jpa.metadata.accessors.ClassAccessor to ensure the xml metadata is processed.

Descriptor Customizer

A descriptor customizer is used to specify a class that implements the org.eclipse.persistence.tools.sessionconfiguration.DescriptorCustomizer interface and that is to be run against a class' descriptor after all metadata processing has been completed. In the case of inheritance, a customizer is not inherited from its parent classes.

customizer

The customizer complex type will be created and the customizer element,

  <xsd:element name="customizer" type="orm:customizer"/>

will be supported on the following complex types:

  • entity
  • mapped-superclass
  • embeddable
  <xsd:complexType name="customizer">
    <xsd:annotation>
      <xsd:documentation>

      @Target({TYPE})
      @Retention(RUNTIME)
      public @interface Customizer {
        /**
         * (Required) Defines the name of the descriptor customizer class that 
         * should be applied for the related entity or embeddable class.
         */
        Class value(); 
      }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="class" type="xsd:string" use="required"/>
  </xsd:complexType>

Example

  <entity name="Employee" class="my.Employee" access="PROPERTY">
    ....
    <customizer class="my.employee.Customizer">
    ....
  </entity>

  <mapped-superclass class="my.Beverage" access="FIELD">
    ....
    <customizer class="my.beverage.Customizer">
    ....
  </mapped-superclass>

  <embeddable class="my.EmploymentPeriod" access="PROPERTY">
    ....
    <customizer class="my.employmentPeriod.Customizer">
    ....
  </embeddable>

Design and processing

  • org.eclipse.persistence.internal.metadata.accessors.xml.XMLClassAccessor will need to override the necessary method(s) from org.eclipse.persistence.internal.metadata.accessors.ClassAccessor to ensure the xml metadata is processed.

read-only

The read-only element,

  <xsd:attribute name="read-only" type="xsd:boolean"/>

is used to specify that a class is read only. In the case of inheritance, a read-only value can only be defined on the root of the inheritance hierarchy. The read-only attribute will be supported on the following complex types:

  • entity
  • mapped-superclass

Example

  <entity name="Employee" class="my.Employee" access="PROPERTY" read-only="true">
    ....
  </entity>

  <mapped-superclass class="my.Beverage" access="FIELD" read-only="false">
    ....
  </mapped-superclass>

Design and processing

  • org.eclipse.persistence.internal.jpa.metadata.accessors.xml.XMLClassAccessor will need to override the necessary methods from org.eclipse.persistence.internal.jpa.metadata.accessors.ClassAccessor to ensure the xml metadata is processed.

Returning policy

Allows for INSERT or UPDATE operations to return values back into the object being written. This allows for table default values, trigger or stored procedures computed values to be set back into the object.

return-insert

The return-insert complex type will be added and the return-insert element,

  <xsd:element name="return-insert" type="orm:return-insert" minOccurs="0"/>

will be supported on the following complex types:

  • basic
  • id
  • version
  <xsd:complexType name="return-insert">
    <xsd:annotation>
      <xsd:documentation>

        @Target({METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface ReturnInsert {
          boolean returnOnly() default false;
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="return-only" type="xsd:boolean"/>
  </xsd:complexType>

Example

  <basic name="areaCode">
    <column name="AREA_CODE"/>
    <return-insert read-only="true"/>
  </basic>

Design and processing

  • org.eclipse.persistence.internal.jpa.metadata.accessors.XMLBasicAccessor will have to override the appropriate method(s) to ensure the xml metadata is used in the processing.

return-update

The return-update complex type will be added and the return-update element,

  <xsd:element name="return-update" type="orm:return-update" minOccurs="0"/>

will be supported on the following complex types:

  • basic
  • id
  • version
  <xsd:complexType name="return-update">
    <xsd:annotation>
      <xsd:documentation>

        @Target({METHOD, FIELD})
        @Retention(RUNTIME)
        public @interface ReturnUpdate {}

      </xsd:documentation>
    </xsd:annotation>
  </xsd:complexType>

Example

  <basic name="firstName">
    <column name="F_NAME"/>
    <return-update/>
  </basic>

Design and processing

  • org.eclipse.persistence.internal.jpa.metadata.accessors.XMLBasicAccessor will have to override the appropriate method(s) to ensure the xml metadata is used in processing.

Stored procedure query

named-stored-procedure-query

A named-stored-procedure-query complex type will be added and will allow the definition of queries that call stored procedures as named queries. These queries will be available from the entity, mapped-superclass and embedabble complex types.

  <xsd:complexType name="named-stored-procedure-query">
    <xsd:annotation>
      <xsd:documentation>

        @Target({TYPE})
        @Retention(RUNTIME)
        public @interface NamedStoredProcedureQuery {
          /**
           * (Required) Unique name that references this stored procedure query.
           */
          String name();

          /**
           * (Optional) Query hints.
           */
          QueryHint[] hints() default {};

          /**
           * (Optional) Refers to the class of the result.
           */
          Class resultClass() default void.class;

          /**
           * (Optional) The name of the SQLResultMapping.
           */
          String resultSetMapping() default "";

          /**
           * (Required) The name of the stored procedure.
           */
          String procedureName();

          /**
           * (Optional) Whether the query should return a result set.
           */
          boolean returnsResultSet() default true; 

          /**
           * (Optional) Defines arguments to the stored procedure.
           */
          StoredProcedureParameter[] procedureParameters() default {};
        }

      </xsd:documentation>
    </xsd:annotation>
      <xsd:sequence>
        <xsd:element name="hint" type="orm:hint" minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="procedure-parameter" type="orm:procedure-parameter" minOccurs="0" maxOccurs="unbounded">
      </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string" use="required"/>
    <xsd:attribute name="result-class" type="xsd:string"/>
    <xsd:attribute name="result-set-mapping" type="xsd:string"/>
    <xsd:attribute name="procedure-name" type="xsd:string" use="required"/>
    <xsd:attribute name="returns-result-set" type="xsd:boolean"/>
  </xsd:complexType>

stored-procedure-parameter

  <xsd:complexType name="stored-procedure-parameter">
    <xsd:annotation>
      <xsd:documentation>

        @Target({})
        @Retention(RUNTIME)
        public @interface StoredProcedureParameter {
          /**
           * (Optional) The direction of the stored procedure parameter.
           */
          Direction procedureParameterDirection() default IN;

          /**
           * (Optional) Stored procedure parameter name.
           */
          String name() default "";

          /**
           * (Required) The query parameter name.
           */
          String queryParameter();

          /**
           * (Optional) The type of Java class desired back from the procedure, 
           * this is dependent on the type returned from the procedure.
           */
          Class type() default void.class;

          /**
           * (Optional) The JDBC type code, this dependent on the type returned 
           * from the procedure.
           */
          int jdbcType() default -1;

          /**
           * (Optional) The JDBC type name, this may be required for ARRAY or 
           * STRUCT types.
           */
          String jdbcTypeName() default "";
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="procedure-parameter-direction" type="orm:direction">
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="query-parameter" type="xsd:string" use="required"/>
    <xsd:attribute name="type" type="xsd:string"/>
    <xsd:attribute name="jdbc-type" type="xsd:integer"/>
    <xsd:attribute name="jdbc-type-name" type="xsd:string"/>
  </xsd:complexType>

direction-type

  <xsd:simpleType name="direction-type">
    <xsd:annotation>
      <xsd:documentation>

        public enum Direction {
          /**
           * Input parameter
           */
          IN,

          /**
           * Output parameter
           */
          OUT,

          /**
           * Input and output parameter
           */
          IN_OUT,

          /**
           * Output cursor
           */
          OUT_CURSOR
        }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:token">
      <xsd:enumeration value="IN"/>
      <xsd:enumeration value="OUT"/>
      <xsd:enumeration value="IN_OUT"/>
      <xsd:enumeration value="OUT_CURSOR"/>
    </xsd:restriction>
  </xsd:simpleType>

Example

  <named-stored-procedure-query name="ReadEmployee" procedureName="Read_Employee">
    <stored-procedure-parameter queryParameter="EMP_ID"/>
  </named-stored-procedure-query>

Design and processing

  • Build new org.eclipse.persistence.internal.jpa.metadata.queries.xml.XMLNamedStoredProcedureQuery that extends org.eclipse.persistence.internal.jpa.metadata.queries.MetadataNamedStoredProcesureQuery. Its sole purpose will be to override the metatada that is processed.
  • Build new org.eclipse.persistence.internal.jpa.metadata.queries.xml.XMLStoredProcedureParameter that extends org.eclipse.persistence.internal.jpa.metadata.queries.MetadataStoredProcesureParameter. Its sole purpose will be to override the metatada that is processed.
  • org.eclipse.persistence.internal.jpa.metadata.accessors.XMLClassAccessor will be responsible for building XMLNamedStoredProcedureQuery's.

Join Fetch

A join fetch setting allows related objects to be joined and read in the same query as the source object. A join-fetch attribute,

  <xsd:attribute name="join-fetch" type="orm:join-fetch-type">

will be supported on the following complex types.

  • one-to-one
  • many-to-one
  • one-to-many
  • many-to-many
  • basic-collection
  • basic-map.

join-fetch-type

  <xsd:simpleType name="join-fetch-type">
    <xsd:annotation>
      <xsd:documentation>

        public enum JoinFetchType {
        /**
         * An inner join is used to fetch the related object.
         * This does not allow for null/empty values.
         */
        INNER,

        /**
         * An inner join is used to fetch the related object.
         * This allows for null/empty values.
         */
        OUTER,
      }

      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:token">
      <xsd:enumeration value="INNER"/>
      <xsd:enumeration value="OUTER"/>
    </xsd:restriction>
  </xsd:simpleType>

Example

  • See basic-collection or basic-map for an example.

Design and processing

  • Processing of the join-fetch type will be done per individual supported mapping accessor classes. For example, org.eclipse.persistence.internal.jpa.metadata.accessors.xml.XMLOneToOneAccessor will be responsible for overriding the necessary method from org.eclipse.persistence.internal.jpa.metadata.accessors.OneToOneAccessor to ensure the xml value is used in the processing. The same holds true for all the other xml mapping accessors and their parent classes.

Mutable

A mutable setting can be used on a basic mapping. It can be used on complex field types to indicate that the value itself can be changed or not changed (instead of being replaced). Mutable basic mappings affect the overhead of change tracking, attribute change tracking can only be weaved with non-mutable mappings.

The mutable element,

  <xsd:attribute name="mutable" type="xsd:boolean">

will be supported on the following complex types:

  • basic

Example

  <basic name="bestBeforeDate" mutable="false">
    <column name="BB_DATE"/>
    <temporal>DATE</temporal>
  </basic>

Design and processing

  • org.eclipse.persistence.internal.jpa.metadata.accessors.xml.XMLBasicAccessor will need to override the necessary method from org.eclipse.persistence.internal.jpa.metadata.accessors.BasicAccessor to esure the xml metadata is processed.

Open items

The following lists contains items of interest that potentially could be added with this iteration, however, go beyond the scope of mirroring currrent EclipseLink annotation support in XML metadata. If they are not to be completed at this time, they will be moved to a further milestone (see Functional Spec .. coming soon). If you feel strongly one way or another on any of these items, please add your comments.

  • Allow relationships and inheritance in embeddable
    • GJPP - Relationships are currently allowed via annotations, so yes I agree, we should add:
      • one-to-one
      • one-to-many
      • many-to-one
      • many-to-many
      • embedded
    • GJPP - Inheritance processing could be added fairly easy as well.
  • xsd allows a join-table on a one-to-one. EclipseLink currently does not support this.
  • xsd allows a join-column on a one-to-many. EclipseLink currently does not support this.

Future enhancements or investigations

These should be added to the Functional spec (coming soon) to be addressed in a later milestone.

Questions or comments

Please add any questions or comments here ...