| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>7. Fetch Groups</title><link rel="stylesheet" href="css/docbook.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.72.0"><link rel="start" href="manual.html" title="Apache OpenJPA User's Guide"><link rel="up" href="ref_guide_pc.html" title="Chapter 5. Persistent Classes"><link rel="prev" href="ref_guide_pc_scos.html" title="6. Persistent Fields"><link rel="next" href="ref_guide_perfpack_eager.html" title="8. Eager Fetching"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. |
| Fetch Groups |
| </th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ref_guide_pc_scos.html">Prev</a> </td><th width="60%" align="center">Chapter 5. |
| Persistent Classes |
| </th><td width="20%" align="right"> <a accesskey="n" href="ref_guide_perfpack_eager.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ref_guide_fetch"></a>7. |
| Fetch Groups |
| </h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ref_guide_fetch.html#ref_guide_fetch_custom">7.1. |
| Custom Fetch Groups |
| </a></span></dt><dt><span class="section"><a href="ref_guide_fetch.html#ref_guide_fetch_conf">7.2. |
| Custom Fetch Group Configuration |
| </a></span></dt><dt><span class="section"><a href="ref_guide_fetch.html#ref_guide_fetch_single_field">7.3. |
| Per-field Fetch Configuration |
| </a></span></dt><dt><span class="section"><a href="ref_guide_fetch.html#ref_guide_fetch_impl">7.4. |
| Implementation Notes |
| </a></span></dt></dl></div><a class="indexterm" name="d0e23184"></a><p> |
| Fetch groups are sets of fields that load together. They can be used to to pool |
| together associated fields in order to provide performance improvements over |
| standard data fetching. Specifying fetch groups allows for tuning of lazy |
| loading and eager fetching behavior. |
| </p><p> |
| The JPA Overview's <a href="jpa_overview_meta_field.html#jpa_overview_meta_fetch" title="2.6.1. Fetch Type">Section 2.6.1, “ |
| Fetch Type |
| ”</a> describes how |
| to use JPA metadata annotations to control whether a field is fetched eagerly or |
| lazily. Fetch groups add a dynamic aspect to this standard ability. As you will |
| see, OpenJPA's JPA extensions allow you can add and remove fetch groups at |
| runtime to vary the sets of fields that are eagerly loaded. |
| </p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_fetch_custom"></a>7.1. |
| Custom Fetch Groups |
| </h3></div></div></div><p> |
| OpenJPA places any field that is eagerly loaded according to the JPA metadata |
| rules into the built-in <span class="emphasis"><em>default</em></span> fetch group. As its name |
| implies, the default fetch group is active by default. You may also |
| define your own named fetch groups and activate or deactivate them at runtime, |
| as described later in this chapter. OpenJPA will eagerly-load the fields in all |
| active fetch groups when loading objects from the datastore. |
| </p><p> |
| You create fetch groups with the |
| <a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/persistence/FetchGroup.html" target="_top"> |
| <code class="classname">org.apache.openjpa.persistence.FetchGroup</code></a> |
| annotation. If your class only has one custom fetch group, you can place this |
| annotation directly on the class declaration. Otherwise, use the |
| <a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/persistence/FetchGroups.html" target="_top"> |
| <code class="classname">org.apache.openjpa.persistence.FetchGroups</code></a> |
| annotation to declare an array of individual <code class="classname">FetchGroup</code> |
| values. The <code class="classname">FetchGroup</code> annotation has the following |
| properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">String name</code>: The name of the fetch group. Fetch group names |
| are global, and are expected to be shared among classes. For example, a shopping |
| website may use a <span class="emphasis"><em>detail</em></span> fetch group in each product class |
| to efficiently load all the data needed to display a product's "detail" page. |
| The website might also define a sparse <span class="emphasis"><em>list</em></span> fetch group |
| containing only the fields needed to display a table of products, as in a search |
| result. |
| </p><p> |
| The following names are reserved for use by OpenJPA: <code class="literal">default</code> |
| , <code class="literal">values</code>, <code class="literal">all</code>, <code class="literal">none</code>, |
| and any name beginning with <code class="literal">jdo</code>, <code class="literal">jpa</code>, or |
| <code class="literal">openjpa</code>. |
| </p></li><li><p> |
| <code class="literal">FetchAttribute[] attributes</code>: The set of persistent fields or |
| properties in the fetch group. |
| </p></li><li><p> |
| <code class="literal">String[] fetchGroups</code>: Other fetch groups whose fields to |
| include in this group. |
| </p></li></ul></div><p> |
| As you might expect, listing a |
| <a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/persistence/FetchAttribute.html" target="_top"> |
| <code class="classname">org.apache.openjpa.persistence.FetchAttribute</code></a> |
| within a <code class="classname">FetchGroup</code> includes the corresponding persistent |
| field or property in the fetch group. Each <code class="classname">FetchAttribute</code> |
| has the following properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">String name</code>: The name of the persistent field or property to |
| include in the fetch group. |
| </p></li><li><p> |
| <code class="literal">recursionDepth</code>: If the attribute represents a relation, the |
| maximum number of same-typed relations to eager-fetch from this field. Defaults |
| to 1. For example, consider an <code class="classname">Employee</code> class with a |
| <code class="literal">manager</code> field, also of type <code class="classname">Employee</code>. |
| When we load an <code class="classname">Employee</code> and the <code class="literal"> |
| manager</code> field is in an active fetch group, the recursion depth (along |
| with the max fetch depth setting, described below) determines whether we only |
| retrieve the target <code class="classname">Employee</code> and his manager (depth 1), |
| or whether we also retrieve the manager's manager (depth 2), or the manager's |
| manager's manager (depth 3), etc. Use -1 for unlimited depth. |
| </p></li></ul></div><div class="example"><a name="ref_guide_fetch_customgroups"></a><p class="title"><b>Example 5.18. |
| Custom Fetch Group Metadata |
| </b></p><div class="example-contents"><p> |
| Creates a <span class="emphasis"><em>detail</em></span> fetch group consisting of the |
| <code class="literal">publisher</code> and <code class="literal">articles</code> relations. |
| </p><pre class="programlisting"> |
| import org.apache.openjpa.persistence.*; |
| |
| @Entity |
| @FetchGroups({ |
| @FetchGroup(name="detail", attributes={ |
| @FetchAttribute(name="publisher"), |
| @FetchAttribute(name="articles") |
| }), |
| ... |
| }) |
| public class Magazine { |
| ... |
| } |
| </pre></div></div><br class="example-break"><p> |
| A field can be a member of any number of fetch groups. A field can also |
| declare a <span class="emphasis"><em>load fetch group</em></span>. |
| When you access a lazy-loaded field for the first time, OpenJPA makes a |
| datastore trip to fetch that field's data. Sometimes, however, you know |
| that whenever you access a lazy field A, you're likely to access lazy fields B |
| and C as well. Therefore, it would be more efficient to fetch the data for A, |
| B, and C in the same datastore trip. By setting A's load fetch group to the |
| name of a <a href="ref_guide_fetch.html" title="7. Fetch Groups">fetch group</a> containing B and |
| C, you can tell OpenJPA to load all of these fields together when A is first |
| accessed. |
| </p><p> |
| Use OpenJPA's |
| <a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/persistence/LoadFetchGroup.html" target="_top"> |
| <code class="classname">org.apache.openjpa.persistence.LoadFetchGroup</code></a> |
| annotation to specify the load fetch group of any persistent field. The value of |
| the annotation is the name of a declared fetch group whose members should be |
| loaded along with the annotated field. |
| </p><div class="example"><a name="ref_guide_fetch_loadgroup"></a><p class="title"><b>Example 5.19. |
| Load Fetch Group Metadata |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| import org.apache.openjpa.persistence.*; |
| |
| @Entity |
| @FetchGroups({ |
| @FetchGroup(name="detail", attributes={ |
| @FetchAttribute(name="publisher"), |
| @FetchAttribute(name="articles") |
| }), |
| ... |
| }) |
| public class Magazine { |
| |
| @ManyToOne(fetch=FetchType.LAZY) |
| @LoadFetchGroup("detail") |
| private Publisher publisher; |
| |
| ... |
| } |
| </pre></div></div><br class="example-break"></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_fetch_conf"></a>7.2. |
| Custom Fetch Group Configuration |
| </h3></div></div></div><a class="indexterm" name="d0e23350"></a><p> |
| <a class="indexterm" name="d0e23357"></a> |
| You can control the default set of fetch groups with the |
| <a href="ref_guide_conf_openjpa.html#openjpa.FetchGroups" title="5.31. openjpa.FetchGroups"><code class="literal">openjpa.FetchGroups</code> |
| </a> configuration property. Set this property to a comma-separated list of |
| fetch group names. |
| </p><p> |
| You can also set the system's default maximum fetch depth with the |
| <a href="ref_guide_conf_openjpa.html#openjpa.MaxFetchDepth" title="5.41. openjpa.MaxFetchDepth"><code class="literal">openjpa.MaxFetchDepth</code> |
| </a> configuration property. The maximum fetch depth determines how "deep" |
| into the object graph to traverse when loading an instance. For example, with |
| a <code class="literal">MaxFetchDepth</code> of 1, OpenJPA will load at most the target |
| instance and its immediate relations. With a <code class="literal">MaxFetchDepth</code> |
| of 2, OpenJPA may load the target instance, its immediate relations, and |
| the relations of those relations. This works to arbitrary depth. In fact, |
| the default <code class="literal">MaxFetchDepth</code> value is -1, which symbolizes |
| infinite depth. Under this setting, OpenJPA will fetch configured relations |
| until it reaches the edges of the object graph. Of course, which relation |
| fields are loaded depends on whether the fields are eager or lazy, and on the |
| active fetch groups. A fetch group member's recursion depth may also limit |
| the fetch depth to something less than the configured maximum. |
| </p><p> |
| OpenJPA's <code class="classname">OpenJPAEntityManager</code> and <code class="classname"> |
| OpenJPAQuery</code> extensions to the standard <code class="classname">EntityManager |
| </code> and <code class="classname">Query</code> interfaces provide access to a |
| <a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/persistence/FetchPlan.html" target="_top"> |
| <code class="classname">org.apache.openjpa.persistence.FetchPlan</code></a> object. |
| The <code class="classname">FetchPlan</code> maintains the set of active fetch groups |
| and the maximum fetch depth. It begins with the groups and depth defined in the |
| <code class="literal">openjpa.FetchGroups</code> and <code class="literal">openjpa.MaxFetchDepth |
| </code> properties, but allows you to add or remove groups and change the |
| maximum fetch depth for an individual <code class="classname">EntityManager</code> or |
| <code class="classname">Query</code> through the methods below. |
| </p><pre class="programlisting"> |
| public FetchPlan addFetchGroup(String group); |
| public FetchPlan addFetchGroups(String... groups); |
| public FetchPlan addFetchGroups(Collection groups); |
| public FetchPlan removeFetchGrop(String group); |
| public FetchPlan removeFetchGroups(String... groups); |
| public FetchPlan removeFetchGroups(Collection groups); |
| public FetchPlan resetFetchGroups(); |
| public Collection<String> getFetchGroups(); |
| public void clearFetchGroups(); |
| public FetchPlan setMaxFetchDepth(int depth); |
| public int getMaxFetchDepth(); |
| </pre><p> |
| <a href="ref_guide_runtime.html" title="Chapter 9. Runtime Extensions">Chapter 9, <i xmlns:xlink="http://www.w3.org/1999/xlink"> |
| Runtime Extensions |
| </i></a> details the <code class="classname"> |
| OpenJPAEntityManager</code>, <code class="classname">OpenJPAQuery</code>, and |
| <code class="classname">FetchPlan</code> interfaces. |
| </p><div class="example"><a name="ref_guide_fetch_conf_query"></a><p class="title"><b>Example 5.20. |
| Using the FetchPlan |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| import org.apache.openjpa.persistence.*; |
| |
| ... |
| |
| OpenJPAQuery kq = OpenJPAPersistence.cast(em.createQuery(...)); |
| kq.getFetchPlan().setMaxFetchDepth(3).addFetchGroup("detail"); |
| List results = kq.getResultList(); |
| </pre></div></div><br class="example-break"></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_fetch_single_field"></a>7.3. |
| Per-field Fetch Configuration |
| </h3></div></div></div><a class="indexterm" name="d0e23441"></a><p> |
| In addition to controlling fetch configuration on a per-fetch-group basis, you |
| can configure OpenJPA to include particular fields in the current fetch |
| plan. This allows you to add individual fields that are not in the |
| default fetch group or in any other active fetch groups to the set of |
| fields that will be eagerly loaded from the database. |
| </p><p> |
| JPA <code class="classname">FetchPlan</code> methods: |
| </p><pre class="programlisting"> |
| public FetchPlan addField(String field); |
| public FetchPlan addFields(String... fields); |
| public FetchPlan addFields(Class cls, String... fields); |
| public FetchPlan addFields(Collection fields); |
| public FetchPlan addFields(Class cls, Collection fields); |
| public FetchPlan removeField(String field); |
| public FetchPlan removeFields(String... fields); |
| public FetchPlan removeFields(Class cls, String... fields); |
| public FetchPlan removeFields(Collection fields); |
| public FetchPlan removeFields(Class cls, Collection fields); |
| public Collection<String> getFields(); |
| public void clearFields(); |
| </pre><p> |
| The methods that take only string arguments use the fully-qualified field name, |
| such as <code class="literal">org.mag.Magazine.publisher</code>. Similarly, <code class="methodname"> |
| getFields</code> returns the set of fully-qualified field names. In all |
| methods, the named field must be defined in the class specified in the |
| invocation, not a superclass. So, if the field <code class="literal">publisher</code> is |
| defined in base class <code class="classname">Publication</code> rather than subclass |
| <code class="classname">Magazine</code>, you must invoke <code class="literal">addField |
| (Publication.class, "publisher")</code> and not <code class="literal">addField |
| (Magazine.class, "publisher")</code>. This is stricter than Java's default |
| field-masking algorithms, which would allow the latter method behavior if |
| <code class="literal">Magazine</code> did not also define a field called <code class="literal"> |
| publisher</code>. |
| </p><p> |
| In order to avoid the cost of reflection, OpenJPA does not perform any |
| validation of the field name / class name pairs that you put into the fetch |
| configuration. If you specify non-existent class / field pairs, nothing adverse |
| will happen, but you will receive no notification of the fact that the specified |
| configuration is not being used. |
| </p><div class="example"><a name="ref_guide_fetch-conf_per_field"></a><p class="title"><b>Example 5.21. |
| Adding an Eager Field |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| import org.apache.openjpa.persistence.*; |
| |
| ... |
| |
| OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); |
| kem.getFetchPlan().addField(Magazine.class, "publisher"); |
| Magazine mag = em.find(Magazine.class, magId); |
| </pre></div></div><br class="example-break"></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_fetch_impl"></a>7.4. |
| Implementation Notes |
| </h3></div></div></div><div class="itemizedlist"><ul type="disc"><li><p> |
| Even when a direct relation is not eagerly fetched, OpenJPA selects the foreign |
| key columns and caches the values. This way when you do traverse the relation, |
| OpenJPA can often find the related object in its cache, or at least avoid joins |
| when loading the related object from the database. |
| </p></li><li><p> |
| The above implicit foreign key-selecting behavior does not always apply when the |
| relation is in a subclass table. If the subclass table would not otherwise be |
| joined into the select, OpenJPA avoids the extra join just to select the foreign |
| key values. |
| </p></li></ul></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ref_guide_pc_scos.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ref_guide_pc.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ref_guide_perfpack_eager.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. |
| Persistent Fields |
| </td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top"> 8. |
| Eager Fetching |
| </td></tr></table></div></body></html> |