JPA : Fetch Groups

When an object is retrieved from the datastore by JPA 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 2 types of "fetch groups" to consider

  • "Default Fetch Group" : defined in all JPA specs, specifying the fetch setting for each field/property (LAZY/EAGER).
  • Named Fetch Groups : standard in JDO but a DataNucleus extension for JPA, and defined in MetaData (annotations) with the fields of a class that are part of that fetch group. The definition here is static

Default Fetch Group

JPA 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. You define this "default" by setting the fetch attribute in metadata for each field/property.


Named Fetch Groups

As mentioned above, JDO allows specification of users own fetch groups (for enabling at particular times) and DataNucleus makes that flexibility available for JPA via annotations. For example, if we have the following class

class MyClass
{
    String name;
    HashSet coll;
    MyOtherClass other;
}

and we want to have the other field loaded whenever we load objects of this class, we define our annotations as

@PersistenceCapable
@FetchGroup(name="otherfield", members={@FetchMember("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.

JPAEntityManager dnEM = (JPAEntityManager)em;
dnEM.getFetchPlan().addGroup("otherfield");

... (load MyClass object)

By default the FetchPlan will include the default fetch group. We have changed this above by adding the fetch group "otherfield", so when we retrieve an object using this EntityManager 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. A big improvement over standard JPA!

The FetchPlan applies not just to calls to EntityManager.find(), but also to EntityManager.createQuery(), as well as detaching.