| :_basedir: |
| :_imagesdir: images/ |
| :grid: cols |
| :usage: |
| |
| [[index]] |
| |
| == Fetch Groupsanchor:Fetch_Groups[] |
| |
| When an object is retrieved from the datastore by JDO typically not all |
| fields are retrieved immediately. This is because for efficiency |
| purposes only particular field types are retrieved in the initial access |
| of the object, and then any other objects are retrieved when accessed |
| (lazy loading). The group of fields that are loaded is called a *fetch |
| group*. There are 3 types of "fetch groups" to consider |
| |
| * xref:dfg[Default Fetch Group] : defined in all JDO specs, containing |
| the fields of a class that will be retrieved by default (with no user |
| specification). |
| * xref:static[Named Fetch Groups] : defined by the JDO2 specification, |
| and defined in MetaData (XML/annotations) with the fields of a class |
| that are part of that fetch group. The definition here is _static_ |
| * xref:dynamic[Dynamic Fetch Groups] : Programmatic definition of fetch |
| groups at runtime via an API |
| |
| The *fetch group* in use for a class is controled via the _FetchPlan_ |
| http://db.apache.org/jdo/api20/apidocs/javax/jdo/FetchPlan.html[image:images/javadoc.png[image]] |
| interface. To get a handle on the current _FetchPlan_ we do |
| |
| .... |
| FetchPlan fp = pm.getFetchPlan(); |
| .... |
| |
| {empty} + |
| |
| anchor:dfg[] |
| |
| === Default Fetch Groupanchor:Default_Fetch_Group[] |
| |
| JDO provides an initial fetch group, comprising the fields that will be |
| retrieved when an object is retrieved if the user does nothing to define |
| the required behaviour. By default the _default fetch group_ comprises |
| all fields of the following types : |
| |
| * primitives : boolean, byte, char, double, float, int, long, short |
| * Object wrappers of primitives : Boolean, Byte, Character, Double, |
| Float, Integer, Long, Short |
| * java.lang.String, java.lang.Number, java.lang.Enum |
| * java.math.BigDecimal, java.math.BigInteger |
| * java.util.Date |
| |
| If you wish to change the *Default Fetch Group* for a class you can |
| update the Meta-Data for the class as follows (for XML) |
| |
| .... |
| <class name="MyClass"> |
| ... |
| <field name="fieldX" default-fetch-group="true"/> |
| </class> |
| .... |
| |
| or using annotations |
| |
| .... |
| @Persistent(defaultFetchGroup="true") |
| SomeType fieldX; |
| .... |
| |
| When a _PersistenceManager_ is created it starts with a FetchPlan of the |
| "default" fetch group. That is, if we call |
| |
| .... |
| Collection fetchGroups = fp.getGroups(); |
| .... |
| |
| this will have one group, called "default". At runtime, if you have been |
| using other fetch groups and want to revert back to the default fetch |
| group at any time you simply do |
| |
| .... |
| fp.setGroup(FetchPlan.DEFAULT); |
| .... |
| |
| {empty} + |
| |
| |
| anchor:static[] |
| |
| === Named Fetch Groupsanchor:Named_Fetch_Groups[] |
| |
| As mentioned above, JDO allows specification of users own fetch groups. |
| These are specified in the MetaData of the class. For example, if we |
| have the following class |
| |
| .... |
| class MyClass |
| { |
| String name; |
| HashSet coll; |
| MyOtherClass other; |
| } |
| .... |
| |
| and we want to have the [.underline]#other# field loaded whenever we |
| load objects of this class, we define our MetaData as |
| |
| .... |
| <package name="mydomain"> |
| <class name="MyClass"> |
| <field name="name"> |
| <column length="100" jdbc-type="VARCHAR"/> |
| </field> |
| <field name="coll" persistence-modifier="persistent"> |
| <collection element-type="mydomain.Address"/> |
| <join/> |
| </field> |
| <field name="other" persistence-modifier="persistent"/> |
| <fetch-group name="otherfield"> |
| <field name="other"/> |
| </fetch-group> |
| </class> |
| </package> |
| .... |
| |
| or using annotations |
| |
| .... |
| @PersistenceCapable |
| @FetchGroup(name="otherfield", members={@Persistent(name="other")}) |
| public class MyClass |
| { |
| ... |
| } |
| .... |
| |
| So we have defined a fetch group called "otherfield" that just includes |
| the field with name _other_. We can then use this at runtime in our |
| persistence code. |
| |
| .... |
| PersistenceManager pm = pmf.getPersistenceManager(); |
| pm.getFetchPlan().addGroup("otherfield"); |
| |
| ... (load MyClass object) |
| .... |
| |
| By default the _FetchPlan_ will include the default fetch group. We have |
| changed this above by [.underline]#adding# the fetch group "otherfield", |
| so when we retrieve an object using this _PersistenceManager_ we will be |
| retrieving the fields _name_ AND _other_ since they are both in the |
| current _FetchPlan_. We can take the above much further than what is |
| shown by defining nested fetch groups in the MetaData. In addition we |
| can change the _FetchPlan_ just before any _PersistenceManager_ |
| operation to control what is fetched during that operation. The user has |
| full flexibility to add many groups to the current *Fetch Plan*. This |
| gives much power and control over what will be loaded and when. |
| |
| The _FetchPlan_ applies not just to calls to |
| _PersistenceManager.getObjectById()_, but also to |
| _PersistenceManager.newQuery()_, _PersistenceManager.getExtent()_, |
| _PersistenceManager.detachCopy_ and much more besides. |
| |
| You can read more about *named fetch-groups* and how to use it with |
| link:attach_detach.html[*attach/detach*] |
| |
| anchor:dynamic[] |
| |
| === Dynamic Fetch Groupsanchor:Dynamic_Fetch_Groups[] |
| |
| The mechanism above provides static fetch groups defined in XML or |
| annotations. That is great when you know in advance what fields you want |
| to fetch. In some situations you may want to define your fields to fetch |
| at run time. This became standard in JDO2.2 It operates as follows |
| |
| .... |
| import org.datanucleus.FetchGroup; |
| |
| // Create a FetchGroup on the PMF called "TestGroup" for MyClass |
| FetchGroup grp = myPMF.getFetchGroup("TestGroup", MyClass.class); |
| grp.addMember("field1").addMember("field2"); |
| |
| // Add this group to the fetch plan (using its name) |
| fp.addGroup("TestGroup"); |
| .... |
| |
| So we use the DataNucleus PMF as a way of creating a FetchGroup, and |
| then register that FetchGroup with the PMF for use by all PMs. We then |
| enable our FetchGroup for use in the FetchPlan by using its group name |
| (as we do for a static group). The FetchGroup allows you to add/remove |
| the fields necessary so you have full API control over the fields to be |
| fetched. |
| |
| {empty} + |
| |
| |
| === Fetch Depthanchor:Fetch_Depth[] |
| |
| The basic fetch group defines which fields are to be fetched. It doesn't |
| explicitly define how far down an object graph is to be fetched. JDO |
| provides two ways of controlling this. |
| |
| The first is to set the *maxFetchDepth* for the _FetchPlan_. This value |
| specifies how far out from the root object the related objects will be |
| fetched. A positive value means that this number of relationships will |
| be traversed from the root object. A value of -1 means that no limit |
| will be placed on the fetching traversal. The default is 1. Let's take |
| an example |
| |
| .... |
| public class MyClass1 |
| { |
| MyClass2 field1; |
| ... |
| } |
| |
| public class MyClass2 |
| { |
| MyClass3 field2; |
| ... |
| } |
| |
| public class MyClass3 |
| { |
| MyClass4 field3; |
| ... |
| } |
| .... |
| |
| and we want to detach _field1_ of instances of _MyClass1_, down 2 levels |
| - so detaching the initial "field1" _MyClass2_ object, and its "field2" |
| _MyClass3_ instance. So we define our fetch-groups like this |
| |
| .... |
| <class name="MyClass1"> |
| ... |
| <fetch-group name="includingField1"> |
| <field name="field1"/> |
| </fetch-group> |
| </class> |
| <class name="MyClass2"> |
| ... |
| <fetch-group name="includingField2"> |
| <field name="field2"/> |
| </fetch-group> |
| </class> |
| .... |
| |
| and we then define the *maxFetchDepth* as 2, like this |
| |
| .... |
| pm.getFetchPlan().setMaxFetchDepth(2); |
| .... |
| |
| A further refinement to this global fetch depth setting is to control |
| the fetching of recursive fields. This is performed via a MetaData |
| setting "recursion-depth". A value of 1 means that only 1 level of |
| objects will be fetched. A value of -1 means there is no limit on the |
| amount of recursion. The default is 1. Let's take an example |
| |
| .... |
| public class Directory |
| { |
| Collection children; |
| ... |
| } |
| .... |
| |
| .... |
| <class name="Directory"> |
| <field name="children"> |
| <collection element-type="Directory"/> |
| </field> |
| |
| <fetch-group name="grandchildren"> |
| <field name="children" recursion-depth="2"/> |
| </fetch-group> |
| ... |
| </class> |
| .... |
| |
| So when we fetch a Directory, it will fetch 2 levels of the _children_ |
| field, hence fetching the children and the grandchildren. |
| |
| === Fetch Sizeanchor:Fetch_Size[] |
| |
| A FetchPlan can also be used for defining the fetching policy when using |
| queries. This can be set using |
| |
| .... |
| pm.getFetchPlan().setFetchSize(value); |
| .... |
| |
| The default is _FetchPlan.FETCH_SIZE_OPTIMAL_ which leaves it to |
| DataNucleus to optimise the fetching of instances. A positive value |
| defines the number of instances to be fetched. Using |
| _FetchPlan.FETCH_SIZE_GREEDY_ means that all instances will be fetched |
| immediately. |
| |