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.
Difference between revisions of "EclipseLink/Development/Incubator/Extensions/NestedFetchGroup"
(→Download and Try) |
|||
Line 1: | Line 1: | ||
− | = Extensions | + | = Extensions Incubator: NestedFetchGroup = |
− | + | <table><tr><td width="75%" valign="top"> | |
− | + | This page captures the requirements and design of Nested FetchGroup as per {{bug|273057}}. The goal is provide support for defining how an entire graph of objects is loaded giving the application developer fine grain control. A FetchGroup (org.eclipse.persistence.queries) currently allows a developer to specify which of the attributes in an entity class are populated when querying from the database. The functionality is limited to the scope of the traget entity of the query but can be created and used dynamically, pre-registered by name, or specified as the default for all queries and find operations. | |
− | + | The proposed enhancement will enable developers to define a hierarchy of nested FetchGroup instances to control the entire retrieval of an entity graph. | |
− | + | == Requirements == | |
− | + | * Provide support for specifying multiple levels of FetchGroup behaviour for a query and use the created FetchGroup with either a JPA Query using a hint, on the native query, or register with a descriptor for use as a named or default FetchGroup | |
+ | * Nested FetchGroup and default FetchGroup | ||
+ | ** If a FetchGroup is specified for a relationship that FetchGroup will be used instead the type's default FetchGroup | ||
+ | ** If a null value is specified for a relationship then no FetchGroup will be used on that relationship's target | ||
+ | </td><td style="background-color: #cff8d9; border-width: 1px; border-style: solid; border-color: #999999; padding: 10px;">__TOC__</td></tr></table> | ||
− | == | + | == Design == |
− | + | This enhancement's design currently involves 3 relatively simple changes | |
+ | |||
+ | * FetchGroup (org.eclipse.persistence.queries) | ||
+ | ** Add a Map of FetchGroup keyed by attribute name to handle the nesting | ||
+ | ** Add accessor methods to get and add nested FetchGroup | ||
+ | ** Add call-back method to apply nested FetchGroup in child queries for relationships | ||
+ | * FetchGroupManager (org.eclipse.persistence.descriptors) | ||
+ | ** Modify setDefaultFetchGroup to ensure that the newly provided FetchGroup replaces any previously populated value on the ReadObjectQuery cached in the descriptor's query manager. | ||
+ | * ForeignReferenceMapping (org.eclipse.persistence.mappings) | ||
+ | ** Add a call-back to the FetchGroup (if one exists on the source query) after creating the target query for populating the relationship. | ||
+ | |||
+ | |||
+ | [[Image:Nested-fetch-group.jpg]] | ||
+ | |||
+ | === Usage Examples === | ||
+ | |||
+ | The following usage examples are provided to illustrate how the new nested FetchGroup support will function. | ||
+ | |||
+ | '''Example: Root with nested 1:1 FetchGroup''' | ||
+ | |||
+ | <source lang="java"> | ||
+ | Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); | ||
+ | query.setParameter("GENDER", Gender.Male); | ||
+ | |||
+ | // Define the fields to be fetched on Employee | ||
+ | FetchGroup empGroup = new FetchGroup(); | ||
+ | empGroup.addAttribute("firstName"); | ||
+ | empGroup.addAttribute("lastName"); | ||
+ | empGroup.addAttribute("address"); | ||
+ | |||
+ | // Define the fields to be fetched on Address | ||
+ | FetchGroup addressGroup = new FetchGroup(); | ||
+ | addressGroup.addAttribute("city"); | ||
+ | addressGroup.addAttribute("postalCode"); | ||
+ | |||
+ | empGroup.addGroup("address", addressGroup); | ||
+ | |||
+ | // Configure the dynamic FetchGroup | ||
+ | query.setHint(QueryHints.FETCH_GROUP, empGroup); | ||
+ | |||
+ | List<Employee> emps = query.getResultList(); | ||
+ | </source> | ||
+ | |||
+ | '''Example: Root with nested FetchGroup for 1:1 and null for 1:M''' | ||
+ | |||
+ | <source lang="java"> | ||
+ | Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); | ||
+ | query.setParameter("GENDER", Gender.Male); | ||
+ | |||
+ | // Define the fields to be fetched on Employee | ||
+ | FetchGroup empGroup = new FetchGroup(); | ||
+ | empGroup.addAttribute("firstName"); | ||
+ | empGroup.addAttribute("lastName"); | ||
+ | empGroup.addAttribute("address"); | ||
+ | |||
+ | // Define the fields to be fetched on Address | ||
+ | FetchGroup addressGroup = new FetchGroup(); | ||
+ | addressGroup.addAttribute("city"); | ||
+ | addressGroup.addAttribute("postalCode"); | ||
+ | |||
+ | empGroup.addGroup("address", addressGroup); | ||
+ | empGroup.addGroup("phoneNumbers", null); | ||
+ | |||
+ | // Configure the dynamic FetchGroup | ||
+ | query.setHint(QueryHints.FETCH_GROUP, empGroup); | ||
+ | |||
+ | List<Employee> emps = query.getResultList(); | ||
+ | </source> | ||
+ | |||
+ | == Open Issues == | ||
+ | |||
+ | * Should a relationships specified in a FetchGroup be forced to load before returning from the initiating query? At present the specification of a relationship attribute will only cause its required fields to be read to build the query for the relationship. If the relationship is configured for lazy loading then the created query will only be triggered when the application uses it. | ||
+ | |||
+ | * Should all of the attribute names used in the FetchGroup(s) be validated against the mappings or should they simply be used if they match and ignored otherwise? | ||
+ | |||
+ | * For a nested FetchGroup should a developer be able to specify the use of a pre-defined named FetchGroup? Currently this is not supported | ||
+ | |||
+ | * How are relationships treated that point to a superclass? How can one specify a fetchgroup for each individual subclass? |
Revision as of 14:50, 14 September 2009
Extensions Incubator: NestedFetchGroup
This page captures the requirements and design of Nested FetchGroup as per bug 273057. The goal is provide support for defining how an entire graph of objects is loaded giving the application developer fine grain control. A FetchGroup (org.eclipse.persistence.queries) currently allows a developer to specify which of the attributes in an entity class are populated when querying from the database. The functionality is limited to the scope of the traget entity of the query but can be created and used dynamically, pre-registered by name, or specified as the default for all queries and find operations. The proposed enhancement will enable developers to define a hierarchy of nested FetchGroup instances to control the entire retrieval of an entity graph. Requirements
|
Design
This enhancement's design currently involves 3 relatively simple changes
- FetchGroup (org.eclipse.persistence.queries)
- Add a Map of FetchGroup keyed by attribute name to handle the nesting
- Add accessor methods to get and add nested FetchGroup
- Add call-back method to apply nested FetchGroup in child queries for relationships
- FetchGroupManager (org.eclipse.persistence.descriptors)
- Modify setDefaultFetchGroup to ensure that the newly provided FetchGroup replaces any previously populated value on the ReadObjectQuery cached in the descriptor's query manager.
- ForeignReferenceMapping (org.eclipse.persistence.mappings)
- Add a call-back to the FetchGroup (if one exists on the source query) after creating the target query for populating the relationship.
Usage Examples
The following usage examples are provided to illustrate how the new nested FetchGroup support will function.
Example: Root with nested 1:1 FetchGroup
Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup empGroup = new FetchGroup(); empGroup.addAttribute("firstName"); empGroup.addAttribute("lastName"); empGroup.addAttribute("address"); // Define the fields to be fetched on Address FetchGroup addressGroup = new FetchGroup(); addressGroup.addAttribute("city"); addressGroup.addAttribute("postalCode"); empGroup.addGroup("address", addressGroup); // Configure the dynamic FetchGroup query.setHint(QueryHints.FETCH_GROUP, empGroup); List<Employee> emps = query.getResultList();
Example: Root with nested FetchGroup for 1:1 and null for 1:M
Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup empGroup = new FetchGroup(); empGroup.addAttribute("firstName"); empGroup.addAttribute("lastName"); empGroup.addAttribute("address"); // Define the fields to be fetched on Address FetchGroup addressGroup = new FetchGroup(); addressGroup.addAttribute("city"); addressGroup.addAttribute("postalCode"); empGroup.addGroup("address", addressGroup); empGroup.addGroup("phoneNumbers", null); // Configure the dynamic FetchGroup query.setHint(QueryHints.FETCH_GROUP, empGroup); List<Employee> emps = query.getResultList();
Open Issues
- Should a relationships specified in a FetchGroup be forced to load before returning from the initiating query? At present the specification of a relationship attribute will only cause its required fields to be read to build the query for the relationship. If the relationship is configured for lazy loading then the created query will only be triggered when the application uses it.
- Should all of the attribute names used in the FetchGroup(s) be validated against the mappings or should they simply be used if they match and ignored otherwise?
- For a nested FetchGroup should a developer be able to specify the use of a pre-defined named FetchGroup? Currently this is not supported
- How are relationships treated that point to a superclass? How can one specify a fetchgroup for each individual subclass?