diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java index f8e662b4c..0975f875f 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java @@ -604,6 +604,8 @@ public class FetchConfigurationImpl int cur; for (int i = 0; max != FetchGroup.DEPTH_INFINITE && i < groups.length; i++) { + // ignore custom groups that are inactive in this configuration + if (!this.hasFetchGroup(groups[i])) continue; cur = meta.getFetchGroup(groups[i]).getRecursionDepth(fm); if (cur == FetchGroup.DEPTH_INFINITE || cur > max) max = cur; @@ -625,7 +627,7 @@ public class FetchConfigurationImpl return avail; return Math.min(max, avail); } - + /** * Return the relation type of the given field. */ diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java index 400b3c88f..69c91bb3e 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java @@ -21,9 +21,11 @@ package org.apache.openjpa.meta; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.ObjectUtils; @@ -74,6 +76,7 @@ public class FetchGroup private final ClassMetaData _meta; private final boolean _readOnly; private List _includes; + private Set _containedBy; private Map _depths; private Boolean _postLoad; @@ -172,6 +175,32 @@ public class FetchGroup } return false; } + + /** + * Sets this receiver as one of the included fetch groups of the given + * parent. + * The parent fecth grop must include this receiver before this call. + * + * @see #includes(String, boolean) + * @see #addDeclaredInclude(String) + */ + public boolean setContainedBy(FetchGroup parent) { + parent.addDeclaredInclude(this.getName()); + if (_containedBy==null) + _containedBy = new HashSet(); + return _containedBy.add(parent.getName()); + } + + /** + * Gets the name of the fetch groups in which this receiver has been + * included. + * + * @see #setContainedBy(FetchGroup) + */ + public String[] getContainedBy() { + return (_containedBy == null) ? new String[0] + : (String[]) _containedBy.toArray(new String[_containedBy.size()]); + } /** * Return the fetch group names declared included by this group. diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java index e549bc430..c8998a7ee 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java @@ -875,6 +875,14 @@ public class AnnotationPersistenceMetaDataParser /** * Create fetch groups. + * If FetchGroup A includes FetchGroup B, then a bi-link is set between + * A and B. Both A and B must be declared in the same Class. + *
+ * Call {@link #parseFetchAttribute(ClassMetaData, + * org.apache.openjpa.meta.FetchGroup, FetchAttribute) only after the + * bi-links have been established, because a field f will not only add the + * fetch group A which explictly includes f to its custom fetch groups but + * also will also add any fetch group B that includes A. */ private void parseFetchGroups(ClassMetaData meta, FetchGroup... groups) { org.apache.openjpa.meta.FetchGroup fg; @@ -885,12 +893,25 @@ public class AnnotationPersistenceMetaDataParser fg = meta.addDeclaredFetchGroup(group.name()); if (group.postLoad()) fg.setPostLoad(true); - for (String s : group.fetchGroups()) + for (String s : group.fetchGroups()) { fg.addDeclaredInclude(s); + } + } + + for (FetchGroup group:groups) { + fg = meta.getFetchGroup(group.name()); + String[] includedFetchGropNames = fg.getDeclaredIncludes(); + for (String includedFectchGroupName:includedFetchGropNames) + meta.getFetchGroup(includedFectchGroupName).setContainedBy(fg); + } + + for (FetchGroup group : groups) { + fg = meta.getFetchGroup(group.name()); for (FetchAttribute attr : group.attributes()) parseFetchAttribute(meta, fg, attr); } } + /** * Set a field's fetch group. @@ -904,6 +925,9 @@ public class AnnotationPersistenceMetaDataParser meta, attr.name())); field.setInFetchGroup(fg.getName(), true); + String[] parentFetchGroups = fg.getContainedBy(); + for (String parentFetchGroup:parentFetchGroups) + field.setInFetchGroup(parentFetchGroup, true); if (attr.recursionDepth() != Integer.MIN_VALUE) fg.setRecursionDepth(field, attr.recursionDepth()); }