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/UserGuide/JPA/Advanced JPA Development/Extensible Entities"

(new doc for extensibility)
m
 
(34 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
----
 +
 +
 +
'''[[Image:Elug_draft_icon.png|Warning]] This page is now obsolete. '''
 +
 +
For current information, please see "JPA Entities and JAXB Beans Extensible" in the ''EclipseLink Solutions Guide'':
 +
http://www.eclipse.org/eclipselink/documentation/latest/solutions/extensible.htm
 +
 +
 +
----
 +
 +
 +
 +
 
{{EclipseLink_UserGuide  
 
{{EclipseLink_UserGuide  
 
|info=y
 
|info=y
Line 7: Line 21:
 
|apis=
 
|apis=
 
* [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/annotations/VirtualAccessMethods.html @VirtualAccessMethods]
 
* [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/annotations/VirtualAccessMethods.html @VirtualAccessMethods]
 +
* [[http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/jpa/JpaEntityManagerFactory.html#refreshMetadata(java.util.Map) RefreshMetadata()]]
 
|examples=y
 
|examples=y
 
|example=
 
|example=
 
*[[EclipseLink/Examples/JPA/Extensibility|Extensible Entities]]
 
*[[EclipseLink/Examples/JPA/Extensibility|Extensible Entities]]
 
}}
 
}}
 +
 
=Extensible Entities=
 
=Extensible Entities=
  
''This feature is new in EclipseLink 2.3.''
+
{{EclipseLink_NewIn
 
+
|version=2.3}}
''This topic is currently under review.''
+
<br><br>.
  
 
Use the <tt>@VirtualAccessMethods</tt> annotation to specify that an entity is extensible. By using virtual properties in an extensible entity, you can specify mappings external to the entity. This allows you to modify the mappings without modifying the entity source file and without redeploying the entity's persistence unit.  
 
Use the <tt>@VirtualAccessMethods</tt> annotation to specify that an entity is extensible. By using virtual properties in an extensible entity, you can specify mappings external to the entity. This allows you to modify the mappings without modifying the entity source file and without redeploying the entity's persistence unit.  
Line 28: Line 44:
 
* Provide an additional source of metadata to be used by an application.  
 
* Provide an additional source of metadata to be used by an application.  
  
To configure extensible entities, you must do the following:
+
To create and support an extensible entity,  
# Configure the entity with <tt>@VirtualAccessMethods</tt> to specify that the entity is extensible and to define virtual properties. See [[#Configuring the Entity| Configuring the Entity]].  
+
 
 +
#Configure the entity. See [[#Configuring the Entity| Configuring the Entity]].  
 
# Include flexible columns in the database table to store the additional data. See [[#Designing the Schema| Designing the Schema]].
 
# Include flexible columns in the database table to store the additional data. See [[#Designing the Schema| Designing the Schema]].
 
# Specify extended mappings in the <tt>eclipselink-orm.xml</tt> file. See [[#Providing Additional Mappings| Providing Additional Mappings]]
 
# Specify extended mappings in the <tt>eclipselink-orm.xml</tt> file. See [[#Providing Additional Mappings| Providing Additional Mappings]]
 
# Configure persistence.xml. See [[#Configuring persistence.xml|Configuring persistence.xml]].
 
# Configure persistence.xml. See [[#Configuring persistence.xml|Configuring persistence.xml]].
  
===Configuring the Entity===
+
==Configuring the Entity==
 +
To configure the entity,
  
Use the <tt>@VirtualAccessMethods</tt> annotation to specify that an entity allows flexible mappings.
+
# [[#Annotate with @VirtualAccessMethods| Annotate with <tt>@VirtualAccessMethods</tt>]]
 +
#  [[#Add get() and set() Methods| Add <tt>get()</tt> and <tt>set()</tt> methods]]
 +
# [[#Add a Data Structure|Add a data structure]]
 +
 
 +
===Annotate with @VirtualAccessMethods===
 +
 
 +
Annotate the entity with <tt>@VirtualAccessMethods</tt> to specify that it is extensible and to define virtual properties.  
 
{{EclipseLink_AttributeTable
 
{{EclipseLink_AttributeTable
 
|caption=@VirtualAccessMethods Attributes
 
|caption=@VirtualAccessMethods Attributes
Line 44: Line 68:
 
<td> The name of the getter method to use for the virtual property This method must take a single <tt>java.lang.String</tt> parameter and return a <tt>java.lang.Object</tt>. </td>
 
<td> The name of the getter method to use for the virtual property This method must take a single <tt>java.lang.String</tt> parameter and return a <tt>java.lang.Object</tt>. </td>
 
<td><tt>get</tt></td>
 
<td><tt>get</tt></td>
<td>No</td>
+
<td>Yes</td>
 
</tr>
 
</tr>
 
<tr>
 
<tr>
 
<td>'''<tt>set</tt>'''</td>
 
<td>'''<tt>set</tt>'''</td>
<td>The name of the setter method to use for the virtual property This method must take a <tt>java.lang.String</tt> parameter and return a <tt>java.lang.Object</tt> parameter.</td>
+
<td>The name of the setter method to use for the virtual property This method must take a <tt>java.lang.String</tt> and a <tt>java.lang.Object</tt> parameter and return a <tt>java.lang.Object</tt> parameter.</td>
 
<td><tt>set</tt></td>
 
<td><tt>set</tt></td>
<td>No</td>
+
<td>Yes</td>
 
</tr>
 
</tr>
 
}}
 
}}
 
<br>
 
 
<br>
 
<br>
An extensible entity class must have a <tt>get()</tt> method that returns a value by property name and a <tt>set()</tt> method that stores a value by property name. The default names for these methods are <tt>get()</tt> and <tt>set()</tt>, and they can be overridden with the <tt>@VirtualAccessMethods</tt> annotation.
 
  
EclipseLink weaves these methods if weaving is enabled, which provides support for lazy loading, change tracking, fetch groups, and internal optimizations.  
+
=== Add get() and set() Methods===
 +
Add <tt>get(String)</tt> and <tt>set(String, Object)</tt> methods to the entity.
 +
 
 +
The <tt>get()</tt> method returns a value by property name and the <tt>set()</tt> method stores a value by property name. The default names for these methods are <tt>get</tt> and <tt>set</tt>, and they can be overridden with the <tt>@VirtualAccessMethods</tt> annotation.
 +
 
 +
EclipseLink weaves these methods if weaving is enabled, which provides support for lazy loading, change tracking, fetch groups, and internal optimizations. You must use the the <tt>get(String)</tt> and <tt>set(String, Object)</tt> signatures, or else weaving will not work.
  
 
{{EclipseLink_Note
 
{{EclipseLink_Note
Line 64: Line 90:
 
}}
 
}}
  
An extended entity stores extended attributes in a <tt>Map</tt>, and values from the <tt>Map</tt> are mapped to the database using an <tt>eclipselink-orm.xml</tt> mapping file.
+
=== Add a Data Structure ===
  
Use the <tt>@Transient</tt> annotation to ...
+
Add a data structure to store the extended attributes and values, that is, the virtual mappings. These can then be mapped to the database. See [[#Providing Additional Mappings| Providing Additional Mappings]].
  
'''''//REVIEWERS: What is the right thing to say about Transient? The MOXy extensibility sample doc says "Use @Transient annotation to prevent the entity from being mapped as an inheritance relationship," but I don't think that is right for JPA> My understanding of transient in JPA is that it means a property or field isn't persisted. So what should be said here about transient? (including, is @Transient ''required'' when specifying virtual properties?) These issues also come up in the explanations for the examples, below, where the design doc says something like " Extensions are mapped in a portable way using Transient ".//'''''
+
A common way to store the virtual mappings is in a <tt>Map</tt> (as shown in the examples in this topic), but you can use other ways, as well. For example you could store the virtual mappings in a directory system.
 +
 
 +
When using field-based access, annotate the data structure with <tt>@Transient</tt> so it cannot use it for another mapping. When using property-based access, <tt>@Transient'</tt> is unnecessary.
  
 
===Example===
 
===Example===
 +
 +
The following example shows an entity that uses property access.
  
 
<source lang="java">
 
<source lang="java">
Line 77: Line 107:
 
   public class Customer{
 
   public class Customer{
 
   
 
   
 +
    @Id
 +
    private int id;
 
...
 
...
 
   
 
   
 
     @Transient
 
     @Transient
 
     private Map<String, Object> extensions;
 
     private Map<String, Object> extensions;
+
 
 
     public <T> T get(String name) {
 
     public <T> T get(String name) {
         return (T) extentions.get(name);
+
         return (T) extensions.get(name);
 
     }
 
     }
 
   
 
   
Line 91: Line 123:
 
</source>
 
</source>
  
===Designing the Schema===
+
===Using XML===
 +
As an alternative to, or in addition to, using <tt>@VirtualAccessMethods</tt>, you can use the <tt><access></tt> and <tt><access-methods></tt> elements, for example:
 +
 
 +
<source lang="xml">
 +
<access>VIRTUAL</access>
 +
<access-methods get-method="get" set-method="set"/>
 +
</source>
 +
 
 +
==Designing the Schema==
  
 
Provide database tables with extra columns for storing flexible mapping data. For example, the following Customer table includes two predefined columns, ID and NAME, and three flexible columns, FLEX_COL1, FLEX_COL2, FLEX_COL3:
 
Provide database tables with extra columns for storing flexible mapping data. For example, the following Customer table includes two predefined columns, ID and NAME, and three flexible columns, FLEX_COL1, FLEX_COL2, FLEX_COL3:
Line 103: Line 143:
  
 
You can then specify which of those flex columns should be used to persist an extended attribute, as described below, in [[#Providing Additional Mappings| Providing Additional Mappings]].
 
You can then specify which of those flex columns should be used to persist an extended attribute, as described below, in [[#Providing Additional Mappings| Providing Additional Mappings]].
===Providing Additional Mappings===
+
 
 +
==Providing Additional Mappings==
  
 
To provide additional mappings, add the mappings to the <tt>eclipselink-orm.xml</tt> file, for example:
 
To provide additional mappings, add the mappings to the <tt>eclipselink-orm.xml</tt> file, for example:
 
   
 
   
 
<source lang="xml">
 
<source lang="xml">
<basic name="idNumber" attribute-type="String">
+
<basic name="idNumber" access="VIRTUAL" attribute-type="String">
 
   <column name="FLEX_COL1"/>
 
   <column name="FLEX_COL1"/>
 
   <access-methods get-method="get" set-method="set"/>
 
   <access-methods get-method="get" set-method="set"/>
Line 114: Line 155:
 
</source>
 
</source>
  
'''''//REVIEWERS: Are there any limitations on the types of mappings that support flexible mappings? Also, do you think anything more should be said about what you have to do in eclipselink-orm.xml?//'''''
+
<!--'''''//REVIEWERS: Are there any limitations on the types of mappings that support flexible mappings? Also, do you think anything more should be said about what you have to do in eclipselink-orm.xml?//'''''
===Configuring persistence.xml===
+
  
Configure persistence unit properties in <tt>persistence.xml</tt> to indicate that the application should retrieve the flexible mappings from the <tt>eclipselink-orm.xml</tt> file,. For example:
+
* ''' I think that part of this will be addressed by anything we do to document using <access-methods> to specify Virtual mappings'''--[[User:Tom.ware.oracle.com|Tom.ware.oracle.com]] 16:04, 28 June 2011 (UTC)
 +
* ''' The XML file simply gets treated as another XML file in the list of XML files. As long as you obey all the rules related to what can be overridden, you can use any kind of mapping.  The challenge in using non-virtual mappings is how to have the data structures that support them make sense when the document is not there. e.g. if you're going to have an extension that uses an instance variable, for the instances of the application that don't use that extension file, how is that instance variable treated - JPA will likely try to use it for a mapping using its defaulting-rules''' --[[User:Tom.ware.oracle.com|Tom.ware.oracle.com]] 16:04, 28 June 2011 (UTC)-->
  
'''''//REVIEWERS Did I get that intro right? Would different wording be better here? The design doc said “Use persistence unit properties to get your application to use the file."//'''''
+
 
 +
==Configuring Persistence Properties and the Data Repository==
 +
 
 +
Configure persistence unit properties to indicate that the application should retrieve the flexible mappings from the <tt>eclipselink-orm.xml</tt> file.  You can set persistence unit properties using <tt>persistence.xml</tt> or by setting properties on the <tt>EntityManagerFactory</tt>, as described in the following sections.
 +
 
 +
For more information about external mappings, see [[#EclipseLink/UserGuide/JPA/Advanced_JPA_Development/External_Mappings|External Mappings]].
 +
 
 +
 
 +
===Configuring persistence.xml===
 +
 
 +
In <tt>persistence.xml</tt>, use the <tt>eclipselink.metadata-source</tt> property to use the default <tt>eclipselink-orm.xml</tt> file. Use the <tt>eclipselink.metadata-source.xml.url</tt> property to use a different file at the specified location. For example, 
  
 
<source lang="xml">
 
<source lang="xml">
Line 126: Line 177:
 
</source>
 
</source>
  
'''''//REVIEWERS What more can be  said about these? See my related questions below, under [[#Configuring the EntityManagerFactory and the Metadata Repository | Configuring the EntityManagerFactory and the Metadata Repository]].//'''''
+
=== Configuring the EntityManagerFactory and the Metadata Repository ===
 +
 
 +
Extensions are added at bootstrap time through access to a metadata repository. The metadata repository is accessed through a class that provides methods to retrieve the metadata it holds. The current release includes a metadata repository implementation that supports XML repositories.
 +
 
 +
Specify the class to use and any configuration information for the metadata repository through persistence unit properties. The entity manager factory integrates additional mapping information from the metadata repository into the metadata it uses to bootstrap.
 +
 
 +
You can provide your own implementation of the MetadataSource interface to access the metadata repository.
 +
Each metadata repository access class must specify an individual set of properties to use to connect to the repository.
 +
 
 +
You can subclass either of the following: *<tt>org.eclipse.persistence.jpa.metadata.MetadataSourceAdapter</tt> *<tt>org.eclipse.persistence.jpa.metadata.XMLMetadataSource</tt>
 +
 
 +
====Example====
 +
In the following example, the properties that begin with <tt>com.foo</tt> are defined by the implementor.
 +
 
 +
<source lang="xml">
 +
<property name="eclipselink.metadata-source" value="com.foo.MetadataRepository"/>
 +
<property name="com.foo.MetadataRepository.location" value="foo://bar"/>
 +
<property name="com.foo.MetadataRepository.extra-data" value="foo-bar"/>
 +
</source>
 +
 
 +
====Refreshing the Metadata Repository====
 +
 
 +
If you change the metadata and you want an <tt>EntityManager</tt> based on the new metadata, you must call <tt>refreshMetadata()</tt> on the <tt>EntityManagerFactory</tt> to refresh the data. The next <tt>EntityManager</tt> will be based on the new metadata. 
 +
 
 +
<tt>refreshMetadata</tt> takes a <tt>Map</tt> of properties, and that map of properties can be used to override the properties previously defined for the metadata-source.
 +
 
 
==Examples ==
 
==Examples ==
 
The following examples illustrate variations on configuring extensible entities.
 
The following examples illustrate variations on configuring extensible entities.
Line 135: Line 211:
 
*Field access is used for non-extension fields.
 
*Field access is used for non-extension fields.
 
*Virtual access is used for extension fields, using defaults <tt>(get(String)</tt> and <tt>set(String, Object))</tt> .
 
*Virtual access is used for extension fields, using defaults <tt>(get(String)</tt> and <tt>set(String, Object))</tt> .
*The <tt>get(String)</tt> and <tt>set(String, Object)</tt> methods will be woven, even if no mappings use them, because of the presence of <tt>@Extensible</tt>.<br>
+
*The <tt>get(String)</tt> and <tt>set(String, Object)</tt> methods will be woven, even if no mappings use them, because of the presence of <tt>@VirtualAccessMethods</tt>.
'''''// REVIEWERS: All the examples make this point about @Extensible, but I don't see @Extensible used elsewhere in this spec, in the Javadoc, or in the [[EclipseLink/Examples/JPA/Extensibility|sample]]; and I don't see <extensible> in eclipselink-orm.xsd. Does it exist? If it does not exist, should this bullet be rewritten to say something new about weaving, or should I delete it?//'''''
+
 
*Extensions are mapped in a portable way by specifying <tt>@Transient</tt>.  
 
*Extensions are mapped in a portable way by specifying <tt>@Transient</tt>.  
'''''// REVIEWERS: See my question earlier about @Transient, under "Configuring the Entity."  In short, what should be said here about using @Transient?//'''''
 
 
  
 
Example 1
 
Example 1
Line 175: Line 248:
 
*Field access is used for non-extension fields.
 
*Field access is used for non-extension fields.
 
* The <tt>@VirtualAccessMethods</tt> annotation overrides methods to be used for getting and setting.  
 
* The <tt>@VirtualAccessMethods</tt> annotation overrides methods to be used for getting and setting.  
* The <tt>getExtension(String)</tt> and <tt>setExtension(String, Object)</tt> methods will be woven, even if no mappings use them, because of the presence of <tt>@Extensible</tt>  
+
*The <tt>get(String)</tt> and <tt>set(String, Object)</tt> methods will be woven, even if no mappings use them, because of the presence of <tt>@VirtualAccessMethods</tt>.<br>
'''''// REVIEWERS: See my question about @Extensible in example 1.//'''''
+
 
*Extensions are mapped in a portable way by specifying <tt>@Transient</tt>.  
 
*Extensions are mapped in a portable way by specifying <tt>@Transient</tt>.  
'''''// REVIEWERS: See my question about @Transient in example 1.//'''''
 
 
* The XML for extended mapping indicates which <tt>get()</tt> and <tt>set()</tt> method to use.
 
* The XML for extended mapping indicates which <tt>get()</tt> and <tt>set()</tt> method to use.
 
  
 
Example 2  
 
Example 2  
Line 212: Line 282:
  
 
<source lang="xml">
 
<source lang="xml">
<basic name="name" attribute-type="String">
+
<basic name="name" access="VIRTUAL" attribute-type="String">
 
       <column name="FLEX_1"/>
 
       <column name="FLEX_1"/>
 
       <access-methods get-method="getExtension" set-method="setExtension"/>
 
       <access-methods get-method="getExtension" set-method="setExtension"/>
Line 222: Line 292:
 
Example 3  illustrates the following:  
 
Example 3  illustrates the following:  
  
* Property access is used for non extension fields.
+
* Property access is used for non-extension fields.
 
*Virtual access is used for extension fields, using defaults <tt>(get(String)</tt> and <tt>set(String, Object)) </tt>  
 
*Virtual access is used for extension fields, using defaults <tt>(get(String)</tt> and <tt>set(String, Object)) </tt>  
* The extensions are mapped in a portable way; no @Transient is required because property access is used.  
+
* The extensions are mapped in a portable way. <tt>@Transient</tt> is not required, because property access is used.  
'''''//REVIEWERS: Why? See also my comments on @Transient in example 1//'''''
+
* The <tt>get(String)</tt> and <tt>set(String, Object)</tt> methods will be woven, even if no mappings use them, because of the presence of <tt>@VirtualAccessMethods</tt>.
* The <tt>get(String)</tt> and <tt>set(String, Object) </tt> methods will be woven, even if no mappings use them, because of the presence of <tt>@Extensible</tt>.
+
<br>
'''''//REVIEWERS: See also comments about <tt>@Extensible</tt> in example 1//'''''
+
  
 
<source lang="java">
 
<source lang="java">
Line 255: Line 324:
  
 
<span id="this">
 
<span id="this">
== Configuring the EntityManagerFactory and the Metadata Repository ==
 
 
'''''//REVIEWERS: I'm not sure about this section. Are these mostly implementation details whose user-facing information is already discussed above? Or should we retain this section to delve deeper into these subjects? If so, please advise what to say here.//'''''
 
 
Extensions are added at bootstrap time through access to a metadata repository. The metadata repository is accessed through a class that provides methods to retrieve the metadata it holds.
 
 
Specify the class to use and any configuration information for the metadata repository through persistence unit properties. The entity manager factory checks the metadata repository while bootstrapping for additional mapping information. If additional mapping information is found, the entity manager factory integrates the into the metadata it uses to bootstrap.
 
 
Two types of metadata repository are supported: XML and database.
 
 
You can provide your own implementation of the class to access the metadata repository.
 
Each metadata repository access class must specify an individual set of properties to use to connect to the repository.
 
'''''//REVIEWERS: Should we provide an example here?//'''''
 
 
===Examples ===
 
'''''//REVIEWERS: Can we say something more about these examples to explain them? What? And should all this information be moved up to [[#Configuring persistence.xml|Configuring persistence.xml]]?//'''''
 
 
====XML File Example====
 
 
<source lang="xml">
 
<property name="eclipselink.metadata-source" value="XML"/>
 
<property name="eclipselink.metadata-source.xml.url" value="foo://bar"/>
 
</source>
 
 
 
====User-Specified Example====
 
 
<source lang="xml">
 
<property name="eclipselink.metadata-source" value="com.foo.MetadataRepository"/>
 
<property name="com.foo.MetadataRepository.location" value="foo://bar"/>
 
<property name="com.foo.MetadataRepository.extra-data" value="foo-bar"/>
 
</source>
 
 
{{EclipseLink_Note
 
|note=Use [[http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/jpa/JpaEntityManagerFactory.html#refreshMetadata(java.util.Map) RefreshMetadata()]] to refresh the metadata repository.
 
}}
 
  
'''''//REVIERWERS: Should that note on refresh metadata be included? Should something more be said about it?//'''''
 
 
{{EclipseLink_JPA }}
 
{{EclipseLink_JPA }}

Latest revision as of 08:03, 17 April 2013



Warning This page is now obsolete.

For current information, please see "JPA Entities and JAXB Beans Extensible" in the EclipseLink Solutions Guide: http://www.eclipse.org/eclipselink/documentation/latest/solutions/extensible.htm





EclipseLink JPA

Eclipselink-logo.gif
EclipseLink
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse Source


Extensible Entities

EL NewIn.png New in version 2.3.



.

Use the @VirtualAccessMethods annotation to specify that an entity is extensible. By using virtual properties in an extensible entity, you can specify mappings external to the entity. This allows you to modify the mappings without modifying the entity source file and without redeploying the entity's persistence unit.

Extensible entities are useful in a multi-tenant (or Software-as-a-Service) environment where a shared, generic application can be used by multiple clients (tenants). Tenants have private access to their own data, as well as to data shared with other tenants. See also Single-Table Multi-Tenancy.

Using extensible entities, you can:

  • Build an application where some mappings are common to all users and some mappings are user-specific.
  • Add mappings to an application after it is made available to a customer (even post-deployment).
  • Use the same EntityManagerFactory to work with data after mappings have changed.
  • Provide an additional source of metadata to be used by an application.

To create and support an extensible entity,

  1. Configure the entity. See Configuring the Entity.
  2. Include flexible columns in the database table to store the additional data. See Designing the Schema.
  3. Specify extended mappings in the eclipselink-orm.xml file. See Providing Additional Mappings
  4. Configure persistence.xml. See Configuring persistence.xml.

Configuring the Entity

To configure the entity,

  1. Annotate with @VirtualAccessMethods
  2. Add get() and set() methods
  3. Add a data structure

Annotate with @VirtualAccessMethods

Annotate the entity with @VirtualAccessMethods to specify that it is extensible and to define virtual properties.

@VirtualAccessMethods Attributes
Attribute Description Default Required?
get The name of the getter method to use for the virtual property This method must take a single java.lang.String parameter and return a java.lang.Object. get Yes
set The name of the setter method to use for the virtual property This method must take a java.lang.String and a java.lang.Object parameter and return a java.lang.Object parameter. set Yes


Add get() and set() Methods

Add get(String) and set(String, Object) methods to the entity.

The get() method returns a value by property name and the set() method stores a value by property name. The default names for these methods are get and set, and they can be overridden with the @VirtualAccessMethods annotation.

EclipseLink weaves these methods if weaving is enabled, which provides support for lazy loading, change tracking, fetch groups, and internal optimizations. You must use the the get(String) and set(String, Object) signatures, or else weaving will not work.

Elug note icon.png

Note: Weaving is not supported when using virtual access methods with OneToOne mappings. If attempted, an exception will be thrown.

Add a Data Structure

Add a data structure to store the extended attributes and values, that is, the virtual mappings. These can then be mapped to the database. See Providing Additional Mappings.

A common way to store the virtual mappings is in a Map (as shown in the examples in this topic), but you can use other ways, as well. For example you could store the virtual mappings in a directory system.

When using field-based access, annotate the data structure with @Transient so it cannot use it for another mapping. When using property-based access, @Transient' is unnecessary.

Example

The following example shows an entity that uses property access.

@Entity
  @VirtualAccessMethods
  public class Customer{
 
    @Id
    private int id;
...
 
    @Transient
    private Map<String, Object> extensions;
 
    public <T> T get(String name) {
        return (T) extensions.get(name);
    }
 
    public Object set(String name, Object value) {
        return extensions.put(name, value);
    }

Using XML

As an alternative to, or in addition to, using @VirtualAccessMethods, you can use the <access> and <access-methods> elements, for example:

<access>VIRTUAL</access>
<access-methods get-method="get" set-method="set"/>

Designing the Schema

Provide database tables with extra columns for storing flexible mapping data. For example, the following Customer table includes two predefined columns, ID and NAME, and three flexible columns, FLEX_COL1, FLEX_COL2, FLEX_COL3:

  • CUSTOMER
    • INTEGER ID
    • VARCHAR NAME
    • VARCHAR FLEX_COL1
    • VARCHAR FLEX_COL2
    • VARCHAR FLEX_CO31

You can then specify which of those flex columns should be used to persist an extended attribute, as described below, in Providing Additional Mappings.

Providing Additional Mappings

To provide additional mappings, add the mappings to the eclipselink-orm.xml file, for example:

<basic name="idNumber" access="VIRTUAL" attribute-type="String">
  <column name="FLEX_COL1"/>
  <access-methods get-method="get" set-method="set"/>
</basic>


Configuring Persistence Properties and the Data Repository

Configure persistence unit properties to indicate that the application should retrieve the flexible mappings from the eclipselink-orm.xml file. You can set persistence unit properties using persistence.xml or by setting properties on the EntityManagerFactory, as described in the following sections.

For more information about external mappings, see External Mappings.


Configuring persistence.xml

In persistence.xml, use the eclipselink.metadata-source property to use the default eclipselink-orm.xml file. Use the eclipselink.metadata-source.xml.url property to use a different file at the specified location. For example,

<property name="eclipselink.metadata-source" value="XML"/>
<property name="eclipselink.metadata-source.xml.url" value="foo://bar"/>

Configuring the EntityManagerFactory and the Metadata Repository

Extensions are added at bootstrap time through access to a metadata repository. The metadata repository is accessed through a class that provides methods to retrieve the metadata it holds. The current release includes a metadata repository implementation that supports XML repositories.

Specify the class to use and any configuration information for the metadata repository through persistence unit properties. The entity manager factory integrates additional mapping information from the metadata repository into the metadata it uses to bootstrap.

You can provide your own implementation of the MetadataSource interface to access the metadata repository. Each metadata repository access class must specify an individual set of properties to use to connect to the repository.

You can subclass either of the following: *org.eclipse.persistence.jpa.metadata.MetadataSourceAdapter *org.eclipse.persistence.jpa.metadata.XMLMetadataSource

Example

In the following example, the properties that begin with com.foo are defined by the implementor.

<property name="eclipselink.metadata-source" value="com.foo.MetadataRepository"/>
<property name="com.foo.MetadataRepository.location" value="foo://bar"/>
<property name="com.foo.MetadataRepository.extra-data" value="foo-bar"/>

Refreshing the Metadata Repository

If you change the metadata and you want an EntityManager based on the new metadata, you must call refreshMetadata() on the EntityManagerFactory to refresh the data. The next EntityManager will be based on the new metadata.

refreshMetadata takes a Map of properties, and that map of properties can be used to override the properties previously defined for the metadata-source.

Examples

The following examples illustrate variations on configuring extensible entities.

Example 1

Example 1 illustrates the following:

  • Field access is used for non-extension fields.
  • Virtual access is used for extension fields, using defaults (get(String) and set(String, Object)) .
  • The get(String) and set(String, Object) methods will be woven, even if no mappings use them, because of the presence of @VirtualAccessMethods.
  • Extensions are mapped in a portable way by specifying @Transient.

Example 1

@Entity
  @VirtualAccessMethods
  public class Address {
 
    @Id
    private int id;
 
    @Transient
    private Map<String, Object> extensions;
 
    public int getId(){
        return id;
    }
 
    public <T> T get(String name) {
        return (T) extentions.get(name);
    }
 
    public Object set(String name, Object value) {
        return extensions.put(name, value);
    }
 
...

Example 2

Example 2 illustrates the following:

  • Field access is used for non-extension fields.
  • The @VirtualAccessMethods annotation overrides methods to be used for getting and setting.
  • The get(String) and set(String, Object) methods will be woven, even if no mappings use them, because of the presence of @VirtualAccessMethods.
  • Extensions are mapped in a portable way by specifying @Transient.
  • The XML for extended mapping indicates which get() and set() method to use.

Example 2

@Entity
  @VirtualAccessMethods(get="getExtension", set="setExtension")
  public class Address {
 
    @Id
    private int id;
 
    @Transient
    private Map<String, Object> extensions;
 
    public int getId(){
        return id;
    }
 
    public <T> T getExtension(String name) {
        return (T) extensions.get(name);
    }
 
    public Object setExtension(String name, Object value) {
        return extensions.put(name, value);
    }
 
...
<basic name="name" access="VIRTUAL" attribute-type="String">
      <column name="FLEX_1"/>
      <access-methods get-method="getExtension" set-method="setExtension"/>
    </basic>

Example 3

Example 3 illustrates the following:

  • Property access is used for non-extension fields.
  • Virtual access is used for extension fields, using defaults (get(String) and set(String, Object))
  • The extensions are mapped in a portable way. @Transient is not required, because property access is used.
  • The get(String) and set(String, Object) methods will be woven, even if no mappings use them, because of the presence of @VirtualAccessMethods.


@Entity
  @VirtualAccessMethods
  public class Address {
 
    private int id;
 
    private Map<String, Object> extensions;
 
    @Id
    public int getId(){
        return id;
    }
 
    public <T> T get(String name) {
        return (T) extensions.get(name);
    }
 
    public Object set(String name, Object value) {
        return extensions.put(name, value);
    }
 
...

Eclipselink-logo.gif
Version: DRAFT
Other versions...

Back to the top