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/MetadataCollection"

m (Example:)
 
(10 intermediate revisions by 2 users not shown)
Line 3: Line 3:
 
====== Enhancement Request: {{bug|330846}}  ======
 
====== Enhancement Request: {{bug|330846}}  ======
  
This feature will help eclipselink users to gather the metadata configurations annotated on/in several different entities on to a single centralized location (class)  for better maintenence over time. The prposed feature will leverage existing standards and convensions for grouping metadata and builds upon the same to further simplify its usage and maintenence.   
+
This feature will help eclipselink users to gather the metadata configurations annotated on/in several different entities on to a single centralized location (class) &nbsp;for better maintenence over time. The prposed feature will leverage existing standards and&nbsp;convensions for grouping metadata and builds upon the same to further simplify its usage and maintenence.&nbsp;<br>
 
+
<br>  
+
  
 
=== List of Requirements:  ===
 
=== List of Requirements:  ===
Line 22: Line 20:
 
The following sections will give in detail the changes and modifications that are required for implementing this feature.  
 
The following sections will give in detail the changes and modifications that are required for implementing this feature.  
  
The Metadata Collection is somewhat similar to the existing support for assembling all metatadata in eclipselink-orm.xml; however, it does not aim to be an all encompassing storehouse for the entire metadata of the project, as is the eclipselink-orm.xml. It is expected to be used to group related metadata for easier maintenance.  
+
The Metadata Collection is somewhat similar to the existing support for assembling all metadata in eclipselink-orm.xml; however, it does not aim to be an all encompassing storehouse for the entire metadata of the project, as is the eclipselink-orm.xml. It is expected to be used to group related metadata for easier maintenance.  
  
 
This &nbsp;feature will be available in both the Java annotations and XML mappings.  
 
This &nbsp;feature will be available in both the Java annotations and XML mappings.  
Line 30: Line 28:
 
===== &nbsp;&nbsp;@MetadataCollection  =====
 
===== &nbsp;&nbsp;@MetadataCollection  =====
 
<pre>/*  
 
<pre>/*  
A Metadata Collection can be defined on any ordinary java class to group related metadata like
+
A Metadata Collection can be defined on any ordinary java class to group related metadata  
named queries, resultset mappings, convertors, query redirectors, etc at a central place rather than  
+
like named queries, resultset mappings, convertors, query redirectors, etc at a central  
on an entity to increase reusability and clarity of code. A central location will also simplify the  
+
place rather than on an entity to increase reusability and clarity of code. A central  
maintenance of these metadata. A eclipselink persistence project can have several classes that have been  
+
location will also simplify the maintenance of these metadata. A eclipselink persistence
marked with Metadata Collection so that the users can group related metadata in to several sets for easier  
+
project can have several classes that have been marked with Metadata Collection so that the
maintenance.
+
users can group related metadata in to several sets for easier maintenance.
  
 
*/
 
*/
Line 45: Line 43:
 
     NamedNativeQueries namedNativeQueries();   
 
     NamedNativeQueries namedNativeQueries();   
 
     NamedStoredProcedureQueries namedStoredProcedureQueries();   
 
     NamedStoredProcedureQueries namedStoredProcedureQueries();   
     SQLResultSetMappings[] resultSetMappings() default {};  
+
     SqlResultSetMappings resultSetMappings();  
 
     Convertors convertors();  
 
     Convertors convertors();  
 
     QueryRedirectors queryRedirectors;
 
     QueryRedirectors queryRedirectors;
 
}
 
}
</pre>  
+
</pre>
====  ====
+
  
 
==== XML Element  ====
 
==== XML Element  ====
  
A metadata complex xml element will be created to group all related metadata together:  
+
A metadata complex xml element will be created to group all related metadata together:<br>  
 
+
<br>  
+
 
<pre>&lt;xs:complexType name="metadata-collection"&gt;  
 
<pre>&lt;xs:complexType name="metadata-collection"&gt;  
  
Line 62: Line 57:
  
 
         &lt;xs:documentation&gt;  
 
         &lt;xs:documentation&gt;  
 +
            /*
 +
              A Metadata Collection can be defined on any ordinary java class to
 +
              group related metadata like named queries, resultset mappings,
 +
              convertors, query redirectors, etc at a central place rather than
 +
              on an entity to increase reusability and clarity of code. A central
 +
              location will also simplify the maintenance of these metadata.
 +
              A eclipselink persistence project can have several classes that
 +
              have been marked with Metadata Collection so that the users can
 +
              group related metadata in to several sets for easier maintenance.
  
 +
            */
 +
 +
            @Target(TYPE)
 +
            @Retention(RUNTIME)
 +
            public @interface MetadataCollection{
 +
                NamedQueries namedQueries();
 +
                NamedNativeQueries namedNativeQueries(); 
 +
                NamedStoredProcedureQueries namedStoredProcedureQueries(); 
 +
                SqlResultSetMappings resultSetMappings();
 +
                Convertors convertors();
 +
                QueryRedirectors queryRedirectors;
 +
            }
 
         &lt;/xs:documentation&gt;&nbsp;  
 
         &lt;/xs:documentation&gt;&nbsp;  
  
Line 69: Line 85:
 
     &lt;xs:sequence&gt;  
 
     &lt;xs:sequence&gt;  
  
         &lt;xs:element name="named-queries" &nbsp;minOccurs="0"&gt;
+
         &lt;xs:element ref="named-queries"/&gt;  
              &lt;xs:element ref="named-query"/&gt;  
+
          
         &lt;/xs:element&gt;
+
         &lt;xs:element ref="named-native-queries" /&gt;  
 
+
          
         &lt;xs:element name="named-native-queries" minOccurs="0"&gt;
+
         &lt;xs:element ref="named-stored-procedure-queries"/&gt;  
              &lt;xs:element ref="named-native-query"/&gt;
+
          
         &lt;/xs:element&gt;
+
         &lt;xs:element ref="sql-resultset-mappings"/&gt;  
 
+
         
         &lt;xs:element name="named-stored-procedure-queries"&gt;
+
         &lt;xs:element ref="convertors"/&gt;  
              &lt;xs:element ref="named-stored-procedure-query"/&gt;  
+
          
         &lt;/xs:element&gt;
+
        &lt;xs:element ref="query-redirectors"/&gt;
 
+
     
         &lt;xs:element name="resultset-mappings" minOccurs="0"&gt;
+
              &lt;xs:element ref="sql-resultset-mapping"/&gt;
+
         &lt;/xs:element&gt;
+
 
+
        &lt;xs:element name="convertors" minOccurs="0"
+
              &lt;xs:element ref="convertor"/&gt;  
+
         &lt;/xs:element&gt;
+
 
+
      &lt;xs:element name="query-redirectors" minOccurs="0"&gt;
+
              &lt;xs:element ref="query-redirector"/&gt;
+
        &lt;/xs:element&gt;
+
 
+
 
     &lt;/xs:sequence&gt;  
 
     &lt;/xs:sequence&gt;  
  
 
&lt;/xs:complexType&gt;  
 
&lt;/xs:complexType&gt;  
  
</pre>  
+
</pre>
 +
 
 
==== <br> Example:  ====
 
==== <br> Example:  ====
 
<pre>@MetadataCollection{
 
<pre>@MetadataCollection{
 
     namedQueries={
 
     namedQueries={
          @NamedQuery(name=SavingsAccountQueries.fetchWithdrawalBalance, query="SELECT account.balance  
+
        @NamedQueries({
                      FROM Account account WHERE account.user=:userName"),
+
              @NamedQuery(name=SavingsAccountQueries.fetchWithdrawalBalance, query="SELECT account.balance  
 
+
                    FROM Account account WHERE account.user=:userName"),
 +
              @NamedQuery(name=SavingsAccountQueries.fetchSomethingElse, query="SELECT account.something
 +
                    FROM Account account WHERE account.user=:userName")
 +
        }),
 
     },
 
     },
 
     namedStoredProcedureQueries={
 
     namedStoredProcedureQueries={
 +
        @NamedStoredProcedureQueries({
 +
              @NamedStoredProcedureQuery(name=SavingsAccountQueries.sampleStoredProcedure,query="select checkBalance(:userName)")
 +
        })
 
     },
 
     },
 
     convertors={
 
     convertors={
          @Convertor(name=SavingsAccountQueries.genderConvertor,
+
        @Convertors({
                convertorClass=com.company.product.module.convertors.GenderConvertor)
+
              @Convertor(name=SavingsAccountQueries.genderConvertor,
     
+
                    convertorClass=com.company.product.module.convertors.GenderConvertor),
 +
              @Convertor(name=SavingsAccountQueries.someOtherConvertor,
 +
                    convertorClass=com.company.product.module.convertors.SomeOtherConvertor)
 +
        })
 
     }
 
     }
 
 
}
 
}
  
Line 118: Line 131:
  
 
     public static final String fetchWithdrawalBalance="fetchWithdrawalBalance";
 
     public static final String fetchWithdrawalBalance="fetchWithdrawalBalance";
 +
    public static final String sampleStoredProcedure="sampleStoredProcedure";
 +
    public static final String fetchSomethingElse="fetchSomethingElse";
 
     public static final String genderConvertor="genderConvertor";
 
     public static final String genderConvertor="genderConvertor";
 
+
    public static final String someOtherConvertor="someOtherConvertor";
 
}  
 
}  
  
</pre> <pre>&lt;metadata-collection&gt;&lt;named-queries&gt; &lt;named-query name="fetchWithdrawalBalance" query="SELECT account.balance FROM Account account WHERE account.userName=:userName"/&gt;  
+
</pre>  
&lt;/named-query&gt;  
+
<br>
&lt;named-native-queries&gt;  
+
<pre>&lt;metadata-collection&gt;
&lt;named-native-query name="" query=""/&gt;  
+
  &lt;named-queries&gt;  
&lt;/named-native-queries&gt;  
+
      &lt;named-query name="fetchWithdrawalBalance" query="SELECT account.balance FROM Account account WHERE account.userName=:userName"/&gt;  
&lt;named-stored-procedure-queries&gt;  
+
  &lt;/named-query&gt;  
&lt;named-stored-procedure-query name="" query="" /&gt;  
+
  &lt;named-native-queries&gt;  
&lt;/named-stored-procedure-queries&gt;  
+
      &lt;named-native-query name="" query=""/&gt;  
&lt;result-set-mappings&gt;  
+
  &lt;/named-native-queries&gt;  
&lt;sql-resultset-mapping&gt;  
+
  &lt;named-stored-procedure-queries&gt;  
    &lt;!-- &lt;entity&gt;and &lt;field&gt; mappings --&gt;  
+
      &lt;named-stored-procedure-query name="" query="" /&gt;  
&lt;/sql-resultset-mapping&gt;  
+
  &lt;/named-stored-procedure-queries&gt;  
&lt;/resultset-mappings&gt;  
+
  &lt;result-set-mappings&gt;  
&lt;convertors&gt;  
+
      &lt;sql-resultset-mapping&gt;  
&lt;convertor name="" class=""&gt;  
+
      &lt;!-- &lt;entity&gt;and &lt;field&gt; mappings --&gt;  
&lt;/convertor&gt;  
+
  &lt;/sql-resultset-mapping&gt;  
&lt;/convertors&gt;  
+
  &lt;/resultset-mappings&gt;  
&lt;query-redirectors&gt;  
+
  &lt;convertors&gt;  
&lt;query-redirector allqueries="DefaultRedirector.class"/&gt;  
+
      &lt;convertor name="" class=""&gt;  
&lt;/query-redirectors&gt;  
+
      &lt;/convertor&gt;  
 +
  &lt;/convertors&gt;  
 +
  &lt;query-redirectors&gt;  
 +
      &lt;query-redirector allqueries="DefaultRedirector.class"/&gt;  
 +
  &lt;/query-redirectors&gt;  
 
&lt;/metadata-collection&gt;
 
&lt;/metadata-collection&gt;
 
</pre>  
 
</pre>  
Line 167: Line 186:
 
This feature does not require any changes in the public facing API of the eclipselink core; however, it does need an important change in the way eclipselink scans for metadata.  
 
This feature does not require any changes in the public facing API of the eclipselink core; however, it does need an important change in the way eclipselink scans for metadata.  
  
Presently only classes that have @Entity or @Embeddale or @MappedSuperClass are searched for resolving JPA metadata; but this feature proposes a facility to group metadata on any ordinary class and hence we need to also search for classes that has @MetadataCollection annoation.  
+
Presently only classes that have @Entity or @Embeddable or @MappedSuperClass are searched for resolving JPA metadata; but this feature proposes a facility to group metadata on any ordinary class and hence we need to also search for classes that has @MetadataCollection annoation.  
  
Also, the metadata objects of type MetadataCollection need to be resolved before any of the contained metadata ( like NamedQueryMetada, SQLResultSetMappingMetadata, etc) is processed so that the contained metadata within each metadata collection can be processed along with similar metadata that has been annotated on enitites and embeddables  
+
Also, the metadata objects of type MetadataCollection need to be resolved before any of the contained metadata ( like NamedQueryMetada, SQLResultSetMappingMetadata, etc) is processed so that the contained metadata within each metadata collection can be processed along with similar metadata that has been annotated on enitites and embeddables
  
 
== Exceptions/Open Issues/Future  ==
 
== Exceptions/Open Issues/Future  ==

Latest revision as of 14:17, 1 December 2010

Metadata Collection Requirements and Design 

Enhancement Request: bug 330846

This feature will help eclipselink users to gather the metadata configurations annotated on/in several different entities on to a single centralized location (class)  for better maintenence over time. The prposed feature will leverage existing standards and convensions for grouping metadata and builds upon the same to further simplify its usage and maintenence. 

List of Requirements:

   This feature should provide eclipselink users the ability to group:

  • all types of related named queries
  • all related resultset mappings
  • all related converters
  • all related query redirectors   

at a central place like any ordinary utility class

Metadata

The following sections will give in detail the changes and modifications that are required for implementing this feature.

The Metadata Collection is somewhat similar to the existing support for assembling all metadata in eclipselink-orm.xml; however, it does not aim to be an all encompassing storehouse for the entire metadata of the project, as is the eclipselink-orm.xml. It is expected to be used to group related metadata for easier maintenance.

This  feature will be available in both the Java annotations and XML mappings.

Annotation:

  @MetadataCollection
/* 
A Metadata Collection can be defined on any ordinary java class to group related metadata 
like named queries, resultset mappings, convertors, query redirectors, etc at a central 
place rather than on an entity to increase reusability and clarity of code. A central 
location will also simplify the maintenance of these metadata. A eclipselink persistence
project can have several classes that have been marked with Metadata Collection so that the
users can group related metadata in to several sets for easier maintenance.

*/
 
@Target(TYPE) 
@Retention(RUNTIME) 
public @interface MetadataCollection{ 
    NamedQueries namedQueries(); 
    NamedNativeQueries namedNativeQueries();  
    NamedStoredProcedureQueries namedStoredProcedureQueries();  
    SqlResultSetMappings resultSetMappings(); 
    Convertors convertors(); 
    QueryRedirectors queryRedirectors;
}

XML Element

A metadata complex xml element will be created to group all related metadata together:

<xs:complexType name="metadata-collection"> 

     <xs:annotation> 

        <xs:documentation> 
             /* 
              A Metadata Collection can be defined on any ordinary java class to 
              group related metadata like named queries, resultset mappings, 
              convertors, query redirectors, etc at a central place rather than
              on an entity to increase reusability and clarity of code. A central 
              location will also simplify the maintenance of these metadata. 
              A eclipselink persistence project can have several classes that 
              have been marked with Metadata Collection so that the users can 
              group related metadata in to several sets for easier maintenance.

             */
 
             @Target(TYPE) 
             @Retention(RUNTIME) 
             public @interface MetadataCollection{ 
                NamedQueries namedQueries(); 
                NamedNativeQueries namedNativeQueries();  
                NamedStoredProcedureQueries namedStoredProcedureQueries();  
                SqlResultSetMappings resultSetMappings(); 
                Convertors convertors(); 
                QueryRedirectors queryRedirectors;
             }
        </xs:documentation>  

     </xs:annotation> 

     <xs:sequence> 

         <xs:element ref="named-queries"/> 
         
         <xs:element ref="named-native-queries" /> 
         
         <xs:element ref="named-stored-procedure-queries"/> 
         
         <xs:element ref="sql-resultset-mappings"/> 
          
         <xs:element ref="convertors"/> 
         
         <xs:element ref="query-redirectors"/>
      
    </xs:sequence> 

</xs:complexType> 


Example:

@MetadataCollection{
     namedQueries={
         @NamedQueries({
              @NamedQuery(name=SavingsAccountQueries.fetchWithdrawalBalance, query="SELECT account.balance 
                     FROM Account account WHERE account.user=:userName"),
              @NamedQuery(name=SavingsAccountQueries.fetchSomethingElse, query="SELECT account.something
                     FROM Account account WHERE account.user=:userName")
         }),
     },
     namedStoredProcedureQueries={
         @NamedStoredProcedureQueries({
              @NamedStoredProcedureQuery(name=SavingsAccountQueries.sampleStoredProcedure,query="select checkBalance(:userName)")
         })
     },
     convertors={
         @Convertors({
              @Convertor(name=SavingsAccountQueries.genderConvertor,
                     convertorClass=com.company.product.module.convertors.GenderConvertor),
              @Convertor(name=SavingsAccountQueries.someOtherConvertor,
                     convertorClass=com.company.product.module.convertors.SomeOtherConvertor)
         })
     }
}

public class SavingsAccountQueries {

    public static final String fetchWithdrawalBalance="fetchWithdrawalBalance";
    public static final String sampleStoredProcedure="sampleStoredProcedure";
    public static final String fetchSomethingElse="fetchSomethingElse";
    public static final String genderConvertor="genderConvertor";
    public static final String someOtherConvertor="someOtherConvertor";
} 


<metadata-collection>
   <named-queries> 
      <named-query name="fetchWithdrawalBalance" query="SELECT account.balance FROM Account account WHERE account.userName=:userName"/> 
   </named-query> 
   <named-native-queries> 
      <named-native-query name="" query=""/> 
   </named-native-queries> 
   <named-stored-procedure-queries> 
      <named-stored-procedure-query name="" query="" /> 
   </named-stored-procedure-queries> 
   <result-set-mappings> 
      <sql-resultset-mapping> 
      <!-- <entity>and <field> mappings --> 
   </sql-resultset-mapping> 
   </resultset-mappings> 
   <convertors> 
      <convertor name="" class=""> 
      </convertor> 
   </convertors> 
   <query-redirectors> 
       <query-redirector allqueries="DefaultRedirector.class"/> 
   </query-redirectors> 
</metadata-collection>

The above named query can be executed in the normal way as shown below:

Query query=entityManager.createNamedQuery(SavingsAccountQueries.fetchWithdrawalBalance);
query.setParameter("userName",userName);
Double balance=(Double)query.getSingleResult();

Metadata Overriding and Merging

The order of precedence for the metadata grouped using this feature will be resolved in the following order descendingly:

  1. eclipselink-orm.xml
  2. orm.xml
  3. @MetadataCollection Annotation
  4. Inhertance of metadata from super class that has been annotated with @MetadataCollection
  5. Individual container annotations for the respective metadata on entity or MappedSuperClass classes

Internal Mapping

Since this annotation is just aggregating several pieces of metadata, and does not have any identity of its own, we do not need to store any mapping for this metadata object, unless we want to provide isolation for metadata defined between two different metadata collections.

Core

This feature does not require any changes in the public facing API of the eclipselink core; however, it does need an important change in the way eclipselink scans for metadata.

Presently only classes that have @Entity or @Embeddable or @MappedSuperClass are searched for resolving JPA metadata; but this feature proposes a facility to group metadata on any ordinary class and hence we need to also search for classes that has @MetadataCollection annoation.

Also, the metadata objects of type MetadataCollection need to be resolved before any of the contained metadata ( like NamedQueryMetada, SQLResultSetMappingMetadata, etc) is processed so that the contained metadata within each metadata collection can be processed along with similar metadata that has been annotated on enitites and embeddables

Exceptions/Open Issues/Future

  • We need to compile the details about which metadata can be centrally defined and which is tightly localised to an entity
  • Can we let any other annotations be defined on non-entity classes?

 

Back to the top