You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by aw...@apache.org on 2007/04/11 18:21:17 UTC

svn commit: r527565 - in /incubator/openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ openj...

Author: awhite
Date: Wed Apr 11 09:21:13 2007
New Revision: 527565

URL: http://svn.apache.org/viewvc?view=rev&rev=527565
Log:
OPENJPA-134 : When we're performing eager fetches and we can detect that we're
already fetching the owning side of a bidi relation, cut off eager selecting 
and loading when we come across the back-ptr to the owner again.


Added:
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java   (with props)
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java   (with props)
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestEagerBidiSQL.java   (with props)
Modified:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCDataImpl.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
    incubator/openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/ObjectData.java

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java Wed Apr 11 09:21:13 2007
@@ -233,26 +233,26 @@
         }
     }
 
-    public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm) {
+    public int getIsolation() {
         try {
-            return getJDBCDelegate().traverseJDBC(fm);
+            return getJDBCDelegate().getIsolation();
         } catch (RuntimeException re) {
             throw translate(re);
         }
     }
 
-    public int getIsolation() {
+    public JDBCFetchConfiguration setIsolation(int level) {
         try {
-            return getJDBCDelegate().getIsolation();
+            getJDBCDelegate().setIsolation(level);
+            return this;
         } catch (RuntimeException re) {
             throw translate(re);
         }
     }
 
-    public JDBCFetchConfiguration setIsolation(int level) {
+    public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm) {
         try {
-            getJDBCDelegate().setIsolation(level);
-            return this;
+            return getJDBCDelegate().traverseJDBC(fm);
         } catch (RuntimeException re) {
             throw translate(re);
         }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java Wed Apr 11 09:21:13 2007
@@ -167,11 +167,6 @@
     public JDBCFetchConfiguration clearJoins();
 
     /**
-     * Convenience method to cast traversal to store-specific type.
-     */
-    public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm);
-
-    /**
      * <p>The isolation level for queries issued to the database. This overrides
      * the persistence-unit-wide <code>openjpa.jdbc.TransactionIsolation</code>
      * value.</p>
@@ -204,4 +199,9 @@
      * @since 0.9.7
      */
     public JDBCFetchConfiguration setIsolation(int level);
+
+    /**
+     * Convenience method to cast traversal to store-specific type.
+     */
+    public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm);
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java Wed Apr 11 09:21:13 2007
@@ -303,25 +303,6 @@
         return this;
     }
 
-    public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm) {
-        return (JDBCFetchConfiguration) traverse(fm);
-    }
-
-    /**
-     * Access JDBC configuration information. May return null if not a
-     * JDBC back-end (possible to get a JDBCFetchConfiguration on non-JDBC
-     * back end in remote client).
-     */
-    private JDBCConfiguration getJDBCConfiguration() {
-        StoreContext ctx = getContext();
-        if (ctx == null)
-            return null;
-        OpenJPAConfiguration conf = ctx.getConfiguration();
-        if (!(conf instanceof JDBCConfiguration))
-            return null;
-        return (JDBCConfiguration) conf;
-    }
-
     public int getIsolation() {
         return _state.isolationLevel;
     }
@@ -341,5 +322,24 @@
         else
             _state.isolationLevel = level;
         return this;
+    }
+
+    public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm) {
+        return (JDBCFetchConfiguration) traverse(fm);
+    }
+
+    /**
+     * Access JDBC configuration information. May return null if not a
+     * JDBC back-end (possible to get a JDBCFetchConfiguration on non-JDBC
+     * back end in remote client).
+     */
+    private JDBCConfiguration getJDBCConfiguration() {
+        StoreContext ctx = getContext();
+        if (ctx == null)
+            return null;
+        OpenJPAConfiguration conf = ctx.getConfiguration();
+        if (!(conf instanceof JDBCConfiguration))
+            return null;
+        return (JDBCConfiguration) conf;
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java Wed Apr 11 09:21:13 2007
@@ -756,8 +756,8 @@
     public Object load(ClassMapping mapping, JDBCFetchConfiguration fetch,
         BitSet exclude, Result result) throws SQLException {
         if (!mapping.isMapped())
-            throw new InvalidStateException(_loc
-                .get("virtual-mapping", mapping));
+            throw new InvalidStateException(_loc.get("virtual-mapping", 
+                mapping));
 
         // get the object id for the row; base class selects pk columns
         ClassMapping base = mapping;
@@ -972,7 +972,7 @@
         if (sm != null && sm.getPCState() != PCState.TRANSIENT
             && sm.getLoaded().get(fm.getIndex()))
             return false;
-        return fetch.requiresFetch(fm);
+        return fetch.requiresFetch(fm) == FetchConfiguration.FETCH_LOAD;
     }
 
     /**
@@ -1127,7 +1127,7 @@
             fms = subMappings[i].getDefinedFieldMappings();
             for (int j = 0; j < fms.length; j++) {
                 // make sure in one of configured fetch groups
-            	if (!fetch.requiresFetch(fms[j]) 
+            	if (fetch.requiresFetch(fms[j]) != FetchConfiguration.FETCH_LOAD
                     && ((!fms[j].isInDefaultFetchGroup() 
                     && fms[j].isDefaultFetchGroupExplicit())
                     || fms[j].supportsSelect(sel, sel.TYPE_TWO_PART, sm, this, 

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java Wed Apr 11 09:21:13 2007
@@ -27,6 +27,7 @@
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.jdbc.sql.SelectExecutor;
+import org.apache.openjpa.kernel.FetchConfiguration;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.StoreContext;
 import org.apache.openjpa.lib.util.Closeable;
@@ -90,7 +91,7 @@
         FieldMapping[] fms = mapping.getDefinedFieldMappings();
         BitSet paged = null;
         for (int i = 0; i < fms.length; i++) {
-            if (!fetch.requiresFetch(fms[i]))
+            if (fetch.requiresFetch(fms[i]) != FetchConfiguration.FETCH_LOAD)
                 continue;
 
             if (fms[i].supportsSelect(sel, sel.EAGER_PARALLEL, null, store,

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java Wed Apr 11 09:21:13 2007
@@ -777,7 +777,7 @@
             StateManagerImpl sm = getStateManagerImplById(oid,
                 (flags & OID_ALLOW_NEW) != 0 || (_flags & FLAG_FLUSHED) != 0);
             if (sm != null) {
-                if (!requiresLoad(sm, true, edata, flags))
+                if (!requiresLoad(sm, true, fetch, edata, flags))
                     return call.processReturn(oid, sm);
 
                 if (!sm.isLoading()) {
@@ -827,7 +827,7 @@
 
             // initialize a new state manager for the datastore instance
             sm = newStateManagerImpl(oid, (flags & OID_COPY) != 0);
-            boolean load = requiresLoad(sm, false, edata, flags);
+            boolean load = requiresLoad(sm, false, fetch, edata, flags);
             sm = initialize(sm, load, fetch, edata);
             if (sm == null) {
                 if ((flags & OID_NOVALIDATE) != 0)
@@ -939,7 +939,7 @@
                     sm = newStateManagerImpl(oid, (flags & OID_COPY) != 0);
 
                 _loading.put(obj, sm);
-                if (requiresLoad(sm, initialized, edata, flags)) {
+                if (requiresLoad(sm, initialized, fetch, edata, flags)) {
                     transState = transState || useTransactionalState(fetch);
                     if (initialized && !sm.isTransactional() && transState)
                         sm.transactional();
@@ -977,7 +977,7 @@
             for (Iterator itr = oids.iterator(); itr.hasNext(); idx++) {
                 oid = itr.next();
                 sm = (StateManagerImpl) _loading.get(oid);
-                if (sm != null && requiresLoad(sm, true, edata, flags)) {
+                if (sm != null && requiresLoad(sm, true, fetch, edata, flags)) {
                     try {
                         sm.load(fetch, StateManagerImpl.LOAD_FGS,
                         	exclude, edata, false);
@@ -1011,7 +1011,9 @@
      * to the user.
      */
     private boolean requiresLoad(OpenJPAStateManager sm, boolean initialized,
-        Object edata, int flags) {
+        FetchConfiguration fetch, Object edata, int flags) {
+        if (!fetch.requiresLoad())
+            return false;
         if ((flags & OID_NOVALIDATE) == 0)
             return true;
         if (edata != null) // take advantage of existing result

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java Wed Apr 11 09:21:13 2007
@@ -436,9 +436,17 @@
 		}
 	}
 
-    public boolean requiresFetch(FieldMetaData fmd) {
+    public int requiresFetch(FieldMetaData fmd) {
         try {
             return _fetch.requiresFetch(fmd);
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public boolean requiresLoad() {
+        try {
+            return _fetch.requiresLoad();
         } catch (RuntimeException re) {
             throw translate(re);
         }

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java Wed Apr 11 09:21:13 2007
@@ -231,9 +231,11 @@
         StateManagerImpl sm, BitSet idxs) {
         FetchConfiguration fetch = broker.getFetchConfiguration();
         FieldMetaData[] fmds = sm.getMetaData().getFields();
-        for (int i = 0; i < fmds.length; i++)
-            if (fmds[i].isPrimaryKey() || fetch.requiresFetch(fmds[i]))
+        for (int i = 0; i < fmds.length; i++) {
+            if (fmds[i].isPrimaryKey() || fetch.requiresFetch(fmds[i])
+                != FetchConfiguration.FETCH_NONE)
                 idxs.set(i);
+        }
     }
 
     /**

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java Wed Apr 11 09:21:13 2007
@@ -40,6 +40,32 @@
     public static final int DEFAULT = -99;
 
     /**
+     * Constant indicating that a field does not require fetching.
+     *
+     * @see #requiresFetch
+     */
+    public static final int FETCH_NONE = 0;
+
+    /**
+     * Constant indicating that a field requires a fetch and load of fetched
+     * data.
+     *
+     * @see #requiresFetch
+     */
+    public static final int FETCH_LOAD = 1;
+
+    /**
+     * Constant indicating that a reference to the field's value must be
+     * fetched, but loading data is not necessary.  Used when we know the
+     * data will be loaded anyway, such as when traversing the back-ptr of
+     * a bidirectional relation where the other side is also being fetched.
+     *
+     * @see #requiresFetch
+     */
+    public static final int FETCH_REF = 2;
+
+
+    /**
      * Return the context assiciated with this configuration;
      * may be null if it has not been set or this object has been serialized.
      */
@@ -309,11 +335,19 @@
 
     /**
      * Affirms if the given field requires to be fetched in the context
-     * of current fetch operation.
+     * of current fetch operation.  Returns one of {@link #FETCH_NONE},
+     * {@link #FETCH_LOAD}, {@link FETCH_REF}.
      *
      * @since 0.4.1
      */
-    public boolean requiresFetch(FieldMetaData fm);
+    public int requiresFetch(FieldMetaData fm);
+
+    /**
+     * Return false if we know that the object being fetched with this
+     * configuration does not require a load, because this configuration came
+     * from a traversal of a {@link #FETCH_REF} field.
+     */
+    public boolean requiresLoad();
     
     /**
      * Traverse the given field to generate (possibly) a new configuration 

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java Wed Apr 11 09:21:13 2007
@@ -39,6 +39,7 @@
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FetchGroup;
 import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.InternalException;
 import org.apache.openjpa.util.NoTransactionException;
@@ -84,6 +85,8 @@
     private FetchConfigurationImpl _parent;
     private String _fromField;
     private Class _fromType;
+    private String _directRelationOwner;
+    private boolean _load = true;
     private int _availableRecursion;
     private int _availableDepth;
 
@@ -126,6 +129,8 @@
         clone._parent = _parent;
         clone._fromField = _fromField;
         clone._fromType = _fromType;
+        clone._directRelationOwner = _directRelationOwner;
+        clone._load = _load;
         clone._availableRecursion = _availableRecursion;
         clone._availableDepth = _availableDepth;
         clone.copy(this);
@@ -498,23 +503,32 @@
     // Traversal
     /////////////
     
-    public boolean requiresFetch(FieldMetaData fm) {
+    public int requiresFetch(FieldMetaData fm) {
         if (!includes(fm))
-            return false;
+            return FETCH_NONE;
         
         Class type = getRelationType(fm);
         if (type == null)
-            return true;
+            return FETCH_LOAD;
         if (_availableDepth == 0)
-            return false;
+            return FETCH_NONE;
 
         // we can skip calculating recursion depth if this is a top-level conf:
         // the field is in our fetch groups, so can't possibly not select
         if (_parent == null) 
-            return true;
+            return FETCH_LOAD;
 
         int rdepth = getAvailableRecursionDepth(fm, type, false);
-        return rdepth == FetchGroup.DEPTH_INFINITE || rdepth > 0;
+        if (rdepth != FetchGroup.DEPTH_INFINITE && rdepth <= 0)
+            return FETCH_NONE;
+
+        if (StringUtils.equals(_directRelationOwner, fm.getFullName()))
+            return FETCH_REF;
+        return FETCH_LOAD;
+    }
+
+    public boolean requiresLoad() {
+        return _load;
     }
 
     public FetchConfiguration traverse(FieldMetaData fm) {
@@ -528,6 +542,15 @@
         clone._fromField = fm.getFullName(false);
         clone._fromType = type;
         clone._availableRecursion = getAvailableRecursionDepth(fm, type, true);
+        if (StringUtils.equals(_directRelationOwner, fm.getFullName()))
+            clone._load = false;
+        else
+            clone._load = _load;
+
+        FieldMetaData owner = fm.getMappedByMetaData();
+        if (owner != null && owner.getTypeCode() == JavaTypes.PC)
+            clone._directRelationOwner = owner.getFullName();
+        
         return clone;
     }
 

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCDataImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCDataImpl.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCDataImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/PCDataImpl.java Wed Apr 11 09:21:13 2007
@@ -138,7 +138,8 @@
             // fields in configured fetch groups
             if (!isLoaded(i))
                 loadIntermediate(sm, fmds[i]);
-            else if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i]))
+            else if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i]) 
+                != FetchConfiguration.FETCH_NONE)
                 loadField(sm, fmds[i], fetch, context);
         }
     }

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java Wed Apr 11 09:21:13 2007
@@ -407,7 +407,8 @@
                     load = !fmds[i].isTransient();
                     break;
                 case LOAD_FGS:
-                    load = fetch == null || fetch.requiresFetch(fmds[i]);
+                    load = fetch == null || fetch.requiresFetch(fmds[i]) 
+                        != FetchConfiguration.FETCH_NONE;
                     break;
                 default: // LOAD_ALL
                     load = true;

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java Wed Apr 11 09:21:13 2007
@@ -131,7 +131,8 @@
                         attachField(manager, toAttach, sm, fmds[i], true);
                         break;
                     case DETACH_FGS:
-                        if (fetch.requiresFetch(fmds[i]))
+                        if (fetch.requiresFetch(fmds[i]) 
+                            != FetchConfiguration.FETCH_NONE)
                             attachField(manager, toAttach, sm, fmds[i], true);
                         break;
                     case DETACH_LOADED:

Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java?view=auto&rev=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java (added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java Wed Apr 11 09:21:13 2007
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.persistence.relations;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+
+@Entity
+public class BidiChild {
+
+    @Id
+    @GeneratedValue
+    private long id;
+
+    private String name;
+
+    @ManyToOne(fetch=FetchType.LAZY)
+    private BidiParent oneToManyParent;
+
+    @OneToOne(fetch=FetchType.LAZY)
+    private BidiParent oneToOneParent;
+
+    public long getId() { 
+        return id; 
+    }
+
+    public String getName() { 
+        return name; 
+    }
+
+    public void setName(String name) { 
+        this.name = name; 
+    }
+
+    public BidiParent getOneToOneParent() { 
+        return oneToOneParent; 
+    }
+
+    public void setOneToOneParent(BidiParent parent) { 
+        oneToOneParent = parent; 
+    }
+
+    public BidiParent getOneToManyParent() { 
+        return oneToManyParent; 
+    }
+
+    public void setOneToManyParent(BidiParent parent) { 
+        oneToManyParent = parent; 
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiChild.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java?view=auto&rev=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java (added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java Wed Apr 11 09:21:13 2007
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.persistence.relations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.OrderBy;
+
+@Entity
+public class BidiParent {
+
+    @Id
+    @GeneratedValue
+    private long id;
+
+    private String name;
+
+    @OneToMany(mappedBy="oneToManyParent")
+    @OrderBy("name ASC")
+    private List<BidiChild> oneToManyChildren = new ArrayList<BidiChild>();
+
+    @OneToOne(fetch=FetchType.LAZY, mappedBy="oneToOneParent")
+    private BidiChild oneToOneChild;
+
+    public long getId() { 
+        return id; 
+    }
+
+    public String getName() { 
+        return name; 
+    }
+
+    public void setName(String name) { 
+        this.name = name; 
+    }
+
+    public BidiChild getOneToOneChild() { 
+        return oneToOneChild; 
+    }
+
+    public void setOneToOneChild(BidiChild child) { 
+        oneToOneChild = child; 
+    }
+
+    public List<BidiChild> getOneToManyChildren() { 
+        return oneToManyChildren; 
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/BidiParent.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestEagerBidiSQL.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestEagerBidiSQL.java?view=auto&rev=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestEagerBidiSQL.java (added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestEagerBidiSQL.java Wed Apr 11 09:21:13 2007
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.persistence.relations;
+
+import java.util.List;
+import javax.persistence.EntityManager;
+
+import junit.textui.TestRunner;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.OpenJPAQuery;
+import org.apache.openjpa.persistence.test.SQLListenerTestCase;
+
+/**
+ * Test that when both sides of a mapped-by relation are eager fetched, 
+ * traversing from the mapped-by side to the mapping side cuts off -- that
+ * we don't traverse in a loop back to the mapped-by side in the generated
+ * SQL.
+ *
+ * @author Abe White
+ */
+public class TestEagerBidiSQL
+    extends SQLListenerTestCase {
+
+    private long id1;
+    private long id2;
+
+    public void setUp() {
+        setUp(BidiParent.class, BidiChild.class);
+        
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+
+        for (int i = 1; i <= 2; i++) {
+            BidiParent parent = new BidiParent();
+            parent.setName("parent" + i);
+            em.persist(parent);
+
+            BidiChild oneOneChild = new BidiChild();
+            oneOneChild.setName("oneToOneChild" + i);
+            oneOneChild.setOneToOneParent(parent);
+            parent.setOneToOneChild(oneOneChild);
+            em.persist(oneOneChild);
+
+            for (int j = 1; j <= 3; j++) {
+                BidiChild oneManyChild = new BidiChild();
+                oneManyChild.setName("oneToManyChild" + i + "::" + j);
+                oneManyChild.setOneToManyParent(parent);
+                parent.getOneToManyChildren().add(oneManyChild);
+                em.persist(oneManyChild);
+            }
+
+            if (i == 1)
+                id1 = parent.getId();
+            else
+                id2 = parent.getId();
+        }
+
+        em.getTransaction().commit();
+        em.close();
+    }
+
+    public void testEagerOwnerOneToManyFind() {
+        sql.clear();
+
+        OpenJPAEntityManager em = emf.createEntityManager();
+        em.getFetchPlan().addField(BidiParent.class, "oneToManyChildren");
+        em.getFetchPlan().addField(BidiChild.class, "oneToManyParent");
+        BidiParent parent = em.find(BidiParent.class, id1);
+        assertEquals(1, sql.size());
+        assertNotSQL(".* LEFT OUTER JOIN BidiParent .*");
+        assertEquals("parent1", parent.getName());
+        assertEquals(3, parent.getOneToManyChildren().size());
+        for (int i = 0; i < 3; i++) {
+            assertEquals("oneToManyChild1::" + (i + 1), 
+                parent.getOneToManyChildren().get(i).getName());
+            assertEquals(parent,
+                parent.getOneToManyChildren().get(i).getOneToManyParent());
+        }
+        assertEquals(1, sql.size());
+        em.close();
+    }
+
+    public void testEagerOwnerOneToOneFind() {
+        sql.clear();
+
+        OpenJPAEntityManager em = emf.createEntityManager();
+        em.getFetchPlan().addField(BidiParent.class, "oneToOneChild");
+        em.getFetchPlan().addField(BidiChild.class, "oneToOneParent");
+        BidiParent parent = em.find(BidiParent.class, id1);
+        assertEquals(1, sql.size());
+        assertNotSQL(".* LEFT OUTER JOIN BidiParent .*");
+        assertEquals("parent1", parent.getName());
+        assertNotNull(parent.getOneToOneChild());
+        assertEquals("oneToOneChild1", parent.getOneToOneChild().getName());
+        assertEquals(parent, parent.getOneToOneChild().getOneToOneParent());
+        assertEquals(1, sql.size());
+        em.close();
+    }
+
+    public void testEagerOwnerOneToManyQuery() {
+        sql.clear();
+
+        OpenJPAEntityManager em = emf.createEntityManager();
+        OpenJPAQuery q = em.createQuery("SELECT o FROM BidiParent o "
+            + "ORDER BY o.name ASC");
+        q.getFetchPlan().addField(BidiParent.class, "oneToManyChildren");
+        q.getFetchPlan().addField(BidiChild.class, "oneToManyParent");
+        List<BidiParent> res = (List<BidiParent>) q.getResultList(); 
+
+        assertEquals(2, res.size());
+        assertEquals(sql.toString(), 2, sql.size());
+        assertNotSQL(".* LEFT OUTER JOIN BidiParent .*");
+
+        for (int i = 0; i < res.size(); i++) {
+            assertEquals("parent" + (i + 1), res.get(i).getName());
+            assertEquals(3, res.get(i).getOneToManyChildren().size());
+            for (int j = 0; j < 3; j++) {
+                assertEquals("oneToManyChild" + (i + 1) + "::" + (j + 1), 
+                    res.get(i).getOneToManyChildren().get(j).getName());
+                assertEquals(res.get(i), res.get(i).getOneToManyChildren().
+                    get(j).getOneToManyParent());
+            }
+        }
+        assertEquals(2, sql.size());
+        em.close();
+    }
+
+    public void testEagerOwnerOneToOneQuery() {
+        sql.clear();
+
+        OpenJPAEntityManager em = emf.createEntityManager();
+        OpenJPAQuery q = em.createQuery("SELECT o FROM BidiParent o "
+            + "ORDER BY o.name ASC");
+        q.getFetchPlan().addField(BidiParent.class, "oneToOneChild");
+        q.getFetchPlan().addField(BidiChild.class, "oneToOneParent");
+        List<BidiParent> res = (List<BidiParent>) q.getResultList(); 
+
+        assertEquals(2, res.size());
+        assertEquals(1, sql.size());
+        assertNotSQL(".* LEFT OUTER JOIN BidiParent .*");
+
+        for (int i = 0; i < res.size(); i++) {
+            assertEquals("parent" + (i + 1), res.get(i).getName());
+            assertNotNull(res.get(i).getOneToOneChild());
+            assertEquals("oneToOneChild" + (i + 1),
+                res.get(i).getOneToOneChild().getName());
+            assertEquals(res.get(i), 
+                res.get(i).getOneToOneChild().getOneToOneParent());
+        }
+        assertEquals(1, sql.size());
+        em.close();
+    }
+
+    public void testEagerNonOwnerOneToOneQuery() {
+        sql.clear();
+
+        OpenJPAEntityManager em = emf.createEntityManager();
+        OpenJPAQuery q = em.createQuery("SELECT o FROM BidiParent o "
+            + "ORDER BY o.name ASC");
+        q.getFetchPlan().addField(BidiParent.class, "oneToOneChild");
+        q.getFetchPlan().addField(BidiChild.class, "oneToManyParent");
+        List<BidiParent> res = (List<BidiParent>) q.getResultList(); 
+
+        assertEquals(2, res.size());
+        assertEquals(1, sql.size());
+        assertSQL(".* LEFT OUTER JOIN BidiParent .*");
+
+        for (int i = 0; i < res.size(); i++) {
+            assertEquals("parent" + (i + 1), res.get(i).getName());
+            assertNotNull(res.get(i).getOneToOneChild());
+            assertEquals("oneToOneChild" + (i + 1),
+                res.get(i).getOneToOneChild().getName());
+            assertNull(res.get(i).getOneToOneChild().getOneToManyParent());
+        }
+        assertEquals(1, sql.size());
+        em.close();
+    }
+
+    public static void main(String[] args) {
+        TestRunner.run(TestEagerBidiSQL.class);
+    }
+}
+

Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestEagerBidiSQL.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/ObjectData.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/ObjectData.java?view=diff&rev=527565&r1=527564&r2=527565
==============================================================================
--- incubator/openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/ObjectData.java (original)
+++ incubator/openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/ObjectData.java Wed Apr 11 09:21:13 2007
@@ -111,7 +111,8 @@
 
         FieldMetaData[] fmds = _meta.getFields();
         for (int i = 0; i < fmds.length; i++)
-            if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i]))
+            if (!sm.getLoaded().get(i) && fetch.requiresFetch(fmds[i]) 
+                != FetchConfiguration.FETCH_NONE)
                 sm.store(i, toLoadable(sm, fmds[i], _data[i], fetch));
     }