JDO2.2 : Dynamic fetch groups
-----------------------------

                 Key: JDO-554
                 URL: https://issues.apache.org/jira/browse/JDO-554
             Project: JDO
          Issue Type: New Feature
          Components: api2, api2-legacy, specification
            Reporter: Andy Jefferson


>From the Apache JDO jdo-dev mailing list, to register the issue for a 
>subsequent JDO release, and holder for any further discussion


Below is a proposal that could possibly be included in a JDO2.2 (or in JDO2.1 
if feedback is positive for that, and JPOX already implements it).

========================================
Problem : fetch groups are static, defined in metadata (XML/annotations). 
Sometimes it would be more convenient to be able to define fetch groups 
dynamically, for example based on user interaction in a web system.

========================================
Proposal :
We add a new interface defining a FetchGroup, where a FetchGroup has a symbolic 
name and is for a class defining the fields of that class that are in the fetch 
group.
public interface FetchGroup
{
    String getName(); // Symbolic name (as also used in MetaData)
    String getClassName(); // Class to which this group refers
    FetchGroup add(String fieldName); // Add a field
    FetchGroup remove(String fieldName); // Remove a field

    boolean hasField(String fieldName);
    String[] getFieldNames();

    void setPostLoad(boolean postLoad);
    boolean getPostLoad();
}

We allow users to register/deregister their FetchGroups with the PMF
PersistenceManagerFactory
{
    ...
    void addFetchGroup(FetchGroup grp);
    void removeFetchGroup(String name, Class cls);
    FetchGroup createFetchGroup(String name, Class cls);
    FetchGroup getFetchGroup(String grpName, Class cls);
    FetchGroup[] getFetchGroups();
    void clearFetchGroups();
}

========================================
Usage:
FetchGroup grp1 = pmf.createFetchGroup("myGroup1", MyClass.class);
grp1.add("field1").add("field2").add("field4");
pmf.addFetchGroup(grp1); // FetchGroup registered

pm.getFetchPlan().setGroup("myGroup1"); // FetchGroup used in this plan
// FetchPlan now has MyClass {field1, field2, field4}

We can then also allow dynamic changes like
pmf.getFetchGroup("myGroup1", MyClass.class).add("field7");
and this is directly reflected in the FetchPlan

Possible changes:-
1. PMF has createFetchGroup and addFetchGroup and we could merge these so when  
creating a FetchGroup it is added
2. Doesnt support "recursion-depth" specification when adding a field to a 
FetchGroup, so we could add a method "add(String fieldName, int depth)"



Comments by Erik Samson
JDO 2 needs alternate ways to define fetch plans. Some food for thoughts here:
-          possibility to add the DFG of a class into a fetch group
-          possibility to add all fields of a class into a fetch group
-          possibility to add all primitive fields of a class into a fetch group
-          possibility to add all reference fields of a class into a fetch group
-          possibility to add all collections fields of a class into a fetch 
group
-          possibility to remove all primitive fields of a class into a fetch 
group
-          possibility to remove all reference fields of a class into a fetch 
group
-          possibility to remove all collections fields of a class into a fetch 
group
-          possibility to create a global fetch plan without fetch groups at all

pm.setFetchPlan( "Person(name,age, address( {dfg} , country( {all} , -flagIMG ) 
), accounts( {simple} , +{references} )           )"   ) ;
Person actually references the candidate class, so I suppose it could be 
optional.
This method will load name and age from a Person, then will load the configured 
DFG from the reference to Address, then will load all fields but flagIMG from 
the reference to Country into address, and finally will load simple fields and 
unary references to other objects from the collection of Accounts. We should 
also probably support depth in that mechanism.
Having this "SSFP" (Single String Fetch Plan) will allow to tune the system 
externally, from JMX or a configuration file for instance.



Comments by Matthew Adams
You might also consider overloaded methods on interface FetchGroup, just for 
completeness:

// (importing java.lang.reflect.Field)
FetchGroup add(Field field);
FetchGroup remove(Field field);
boolean hasField(Field field); // or has(Field) -- I'd consider  better verb
Field[] getFields();

The add & remove methods should throw if the Field isn't contained in the class.



Comments by Christiaan:
May be also think about an option to restore to a fetchGroup to a state before 
you start changing it (possibly via supporting clone()) or reset to 
configuration defined in JDO file. 



Comments by Craig Russell:
Also, I think that we should consider ways to manipulate FetchPlans as well, 
both in programmatic as well as declarative approaches. Specifically, I'd like 
to be able to specify in my configuration the FetchPlan to use in a specific 
application context, e.g. the first time a PersistenceManager is used to 
getObjectById or newQuery, the FetchPlan for that use case is looked up from 
configuration and set as the current FetchPlan.

Further, if the application wants a specific FetchPlan, they should be able to 
call a method setFetchPlan with either the name of a configured FetchPlan or a 
FetchPlan to use.

And then, assuming that the FetchPlan must change during some interval of 
application processing, and then reset to the previous  settings, 
public void pushFetchPlan(FetchPlan); 
public void pushFetchPlan(String fetchPlanName) 
public FetchPlan popFetchPlan() 
would allow a temporary override of the FetchPlan without the application 
having to preserve the settings and update the FetchPlan to restore it.

In this light, it might make sense to be able to register FetchPlans by name 
with the PersistenceManagerFactory.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to