[
https://issues.apache.org/jira/browse/JDO-554?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12620369#action_12620369
]
Craig Russell commented on JDO-554:
-----------------------------------
I think we need to be careful about managing the scope of FetchGroups. Changing
a FetchGroup in the PMF has global ramifications, as it would affect every PM
related to that PMF.
I'd like to examine the use cases. The first one that comes to mind is an
application that wants some specific behavior that is not defined in metadata,
such as adding a specific field or set of fields to a FetchPlan so the fields
are automatically fetched in the scope of this application's usage. For this
use case, the ability to add new fetch groups scoped to the PM suffices,
because the existing addFetchGroup method can add the new fetch group to the
fetch plan in use by the PM.
So I'm fine with
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 or property
FetchGroup remove(String fieldName); // Remove a field or property
boolean hasField(String fieldName); // field or property name, same as
getFieldNames.contains(fieldName) so do we need it?
String[] getFieldNames();
void setPostLoad(boolean postLoad);
boolean getPostLoad();
}
Scoping FetchGroup to PM would require a factory in PM, such as FetchGroup
createFetchGroup(Class cls, String name) and FetchGroup findFetchGroup(Class
cls, String name) that might be combined: FetchGroup getFetchGroup(Class cls,
String name) that does both.
And I'd be happy to add some convenience methods to FetchGroup as Eric Samson
suggests, by making it possible to add and remove default fetch group fields,
primitive fields, reference fields, and multi-valued fields. Maybe something
like this:
FetchGroup addCategory("default"); // define constants using Enum or Strings in
javax.jdo.Constants
And having a language to specify fetch groups and/or fetch plans is a cool
idea. I could see this used in properties, xml, and API.
Regarding Matthew's suggestion adding Field parameters, I don't think this
translates well because JDO treats field names and property names equivalently
and adding Method parameters would just make it more obscure.
Regarding new methods in PMF, we have a scope issue, a security issue, and a
concurrency issue. Any old application that changes fetch groups can affect
other applications. The method would need to be protected, just as we protect
PMF.close. Concurrency is an issue when fetch groups are changing underneath an
application, especially when using the LOAD_FIELDS and UNLOAD_FIELDS flags. An
application assumes that a specific set of fields is being loaded or unloaded,
and some other application changes the behavior in the middle of a transaction?
Bottom line:
I'm happy with dynamically defining new fetch groups and scoping them to PM.
This would be a good start for this round.
I'd be delighted to have a language to define fetch groups that isn't based on
xml, so the definitions could be added to a jdoconfig.xml or a properties file
or used in the API.
I'm not so keen on global scope (PMF-wide) for fetch groups but I'm open to
discussing use cases.
> 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
> Fix For: JDO 2 maintenance release 2
>
>
> 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.