Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Development/Dynamic"

(Dynamic Model)
(Dynamic Model)
Line 186: Line 186:
  
 
=== Dynamic Model ===
 
=== Dynamic Model ===
[[Image:dynpersist.png|750px]]
+
[[Image:dynpersist.png|1000px]]
  
 
The dynamic model is the bulk of this feature. It provides dynamic classes to the application based on a common abstract base entity class which contains all of the EclipseLink specific support. In addition to the entity class itself there is also a simple Type-Property meta-model so that consuming applications can use the entities based on the mapping metadata.
 
The dynamic model is the bulk of this feature. It provides dynamic classes to the application based on a common abstract base entity class which contains all of the EclipseLink specific support. In addition to the entity class itself there is also a simple Type-Property meta-model so that consuming applications can use the entities based on the mapping metadata.

Revision as of 14:05, 31 August 2009

EclipseLink Dynamic Persistence

This page captures the functional requirements and design of a dynamic persistence solution that will allow consumers to specify their mappings. The purpose of dynamic persistence is to enable simplified data access where only mapping information is required and no concrete Java model is required.

The work is being tracked by bug 200045 and is scheduled for inclusion in EclipseLink 1.2

Terminology

Dynamic Persistence is defined as the ability to create a dynamic persistent entity and use it within an application without a-priori the entity's Java .class being present on the classpath (or in some .jar/.war archive).

The purpose of Dynamic Persistence is to enable simplified data access where only mapping information is required and no concrete Java model is required. This allows applications with dynamic storage requirements to avoid coupling to static classes or require specialized handling of new types. The application uses standard EclipseLink APIs to read, create, modify, and remove dynamic persistent entities from their data stores based on types that are either defined in XML mapping files or are constructed within the running application.


Static Configuration

A static configuration defines the dynamic persistent entity's structure and mappings in XML packaged with the application. This is used when the entity is generated before/during deployment and no runtime alteration of its structure is required.

Dynamic Configuration

A dynamic configuration defines the dynamic persistent entity's structure and mappings at runtime, as part of the running application.

Functional Requirements

  1. Ability to use dynamic persistence through standard JPA metadata and interfaces as well as leveraging advanced EclipseLink JPA features
    • Specify mapping metadata using persistence.xml and eclipselink-orm.xml.
    • Create dynamic types at runtime
    • Access dynamic types through standard (JPA2) metamodel + helpers
    • Support removal of dynamic types
  2. Ability to use dynamic persistence through MOXy mappings
  3. Ability to use dynamic persistence within DBWS to share common infrastructure
  4. Ability to use dynamic persistence within SDO to share common infrastructure

Future Features (Current Limitations)

In order to control the scope of this feature the following limitations have been intended and are listed here as potential future enhancements.

  1. Flexible Base Class: This feature assumes the dynamic entity base class. In the future users may want the flexibility to specify a class of their own.
  2. LimitedMapping Capability: This feature does not provide support for all mapping types. The mappings currently not supported include:
    • Inheritance
    • Embedded/EmbeddedId
    • Composite primary keys
  3. Hybrid Classes: This feature only supports DynamicEntity persistent classes. In the future developers may want the ability to combine static java classes with one or more attributes accessed dynamically. The DynamicEntityImpl class provides support for lazy loading, fetch-groups, and attribute change-tracking. Combining this with traditional static attributes and weaving complex.
  4. Native ORM: This feature relies on the JPA metadata processing of eclipselink-orm.xml. When this XML is supported through the native API then dynamic persistence should function as well

Incubator Exit Criteria

In order to exit the incubator and become part of the Core/JPA/MOXy/SDO/DBWS components we must get consensus on the usage of this functionality and it must be able to function as the base dynamic solution in all components.

Design

The design of this feature involves several enhancements to the foundation (Core) component as well as JPA. The high level design involves:

  • XML Configuration: Extension of the eclipselink_orm_1_1.xsd
    • Add support for DYNAMIC access type in addition to FIELD and PROPERTY. Note: DYNAMIC can only be specified within this XML
    • Add support for @attribute-type on all mapping types
  • Dynamic Model
    • Public interfaces: org.eclipse.persistence.dynamic
    • Internal implementation: org.eclipse.persistence.internal.dynamic
  • Metadata Processing Enhancements
    • Handling additional access type
    • Using attribute-type instead of reflective type checking on classes
    • Error handling for configuration limitations

XML Configuration

The change to the eclipselink_orm_1_1.xsd to enable dynamic persistence include:

  • Adding DYNAMIC Access Type. Since this implementation only supports DYNAMIC at the class level it must be set in the persistence unit defaults or individually on each entity. If DYNAMIC is specified for an entity then no attribute can specify a different access type or an exception will be thrown during validation of the metadata.
  • Adding of @access-type mappings to specify the Java type to be used
    • basic, id, version: specifies the 'basic' type to use
    • one-to-many, many-to-many, basic-collection, basic-map: In these mappings the attribute-type specifies the collection/map type to use
<?xml version="1.0" encoding="windows-1252" ?>
<entity-mappings
	xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
	<persistence-unit-metadata>
		<xml-mapping-metadata-complete />
		<exclude-default-mappings />
		<persistence-unit-defaults>
			<access>DYNAMIC</access> 
		</persistence-unit-defaults>
	</persistence-unit-metadata>
 
	<object-type-converter name="gender" object-type="java.lang.String"
		data-type="java.lang.String">
		<conversion-value object-value="Male" data-value="M" />
		<conversion-value object-value="Female" data-value="F" />
	</object-type-converter>
 
	<named-query name="Employee.findAll">
		<query>SELECT e FROM Employee e ORDER BY e.id</query>
	</named-query>
 
	<entity class="model.Address">
		<table name="D_ADDR" />
		<attributes>
			<id name="id" attribute-type="java.lang.Integer">
				<column name="ADDRESS_ID" />
				<generated-value />
			</id>
			<basic name="city" attribute-type="java.lang.String" />
			<basic name="country" attribute-type="java.lang.String" />
			<basic name="province" attribute-type="java.lang.String" />
			<basic name="postalCode" attribute-type="java.lang.String">
				<column name="P_CODE" />
			</basic>
			<basic name="street" attribute-type="java.lang.String" />
		</attributes>
	</entity>
	<entity class="model.PhoneNumber">
		<table name="D_PHONE" />
		<attributes>
			<id name="id" attribute-type="java.lang.Integer">
				<column name="EMP_ID" updatable="false" insertable="false" />
			</id>
			<id name="type" attribute-type="java.lang.String">
				<column updatable="false" />
			</id>
			<basic name="areaCode" attribute-type="java.lang.String">
				<column name="AREA_CODE" />
			</basic>
			<basic name="number" attribute-type="java.lang.String">
				<column name="P_NUMBER" />
			</basic>
			<many-to-one name="owner" target-entity="model.Employee" fetch="LAZY">
				<join-column name="EMP_ID" />
			</many-to-one>
		</attributes>
	</entity>
	<entity class="model.Employee">
		<table name="D_EMP" />
		<attributes>
			<id name="id" attribute-type="java.lang.Integer">
				<column name="EMP_ID" />
				<generated-value />
			</id>
			<basic name="firstName" attribute-type="java.lang.String">
				<column name="F_NAME" />
			</basic>
			<basic name="middleInitial" attribute-type="java.lang.String">
				<column name="INITIAL" />
			</basic>
			<basic name="lastName" attribute-type="java.lang.String">
				<column name="L_NAME" />
			</basic>
			<basic name="startTime" attribute-type="java.sql.Time" fetch="LAZY">
				<column name="START_TIME" />
			</basic>
			<basic name="endTime" attribute-type="java.sql.Time" fetch="LAZY">
				<column name="END_TIME" />
			</basic>
			<basic name="gender" attribute-type="java.lang.String">
				<column name="GENDER" />
				<convert>gender</convert>
			</basic>
			<basic name="salary" attribute-type="java.lang.Double" />
			<version name="version" attribute-type="java.lang.Long">
			</version>
			<many-to-one name="manager" fetch="LAZY" target-entity="model.Employee">
				<join-column name="MANAGER_ID" />
			</many-to-one>
			<one-to-many name="employees" mapped-by="manager"
				target-entity="model.Employee" attribute-type="java.util.ArrayList" />
			<one-to-many name="phoneNumbers" target-entity="model.PhoneNumber"
				mapped-by="owner" attribute-type="java.util.ArrayList">
				<cascade>
					<cascade-all />
				</cascade>
				<private-owned />
			</one-to-many>
			<one-to-one name="address" target-entity="model.Address"
				fetch="LAZY">
				<join-column name="ADDR_ID" />
				<cascade>
					<cascade-all />
				</cascade>
				<private-owned />
			</one-to-one>
		</attributes>
	</entity>
</entity-mappings>

Dynamic Model

Dynpersist.png

The dynamic model is the bulk of this feature. It provides dynamic classes to the application based on a common abstract base entity class which contains all of the EclipseLink specific support. In addition to the entity class itself there is also a simple Type-Property meta-model so that consuming applications can use the entities based on the mapping metadata.

Public Interfaces

The package org.eclipse.persistence.dynamic will provide a set of interfaces that consumers can use when interacting with dynamic entities.

  • DynamicEntity
  • DynamicEntityException
  • DynamicHelper
  • EntityType
  • EntityTypeBuilder

Internal Implementation

The package org.eclipse.persistence.internal.dynamic includes the concrete implementation of the base entity class as well as the meta-model bridge and the byte-code weaving support for creating the concrete dynamic entity classes on the fly.

  • BaseEntityImpl
    • DynamicEntityImpl
  • DynamicClassLoader
  • DynamicClassWriter
  • EntityTypeImpl
  • EntityTypeInstantiationPolicy
  • ValuesAccessor

Metadata Processing

The enhancements to the metadata processing include:

  • Reading the attribute-type into the XML meta-model and ensuring it is processed into the JPA meta-model
  • Handling of the 3 access types in the accessor model
  • Usage of the DynamicClassLoader wrapper when any class in a PU specifies DYNAMIC access
  • Creation of Dynamic class when needed
  • Avoid validation exceptions when dynamic types are used

Back to the top