You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by cu...@apache.org on 2011/08/15 18:36:07 UTC

svn commit: r1157903 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/

Author: curtisr7
Date: Mon Aug 15 16:36:07 2011
New Revision: 1157903

URL: http://svn.apache.org/viewvc?rev=1157903&view=rev
Log:
OPENJPA-2039: Select FKs for fields that are in the DFG, but not in active fetchplan.

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/OptSelectEntity.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestJDBCStoreOptSelect.java   (with props)
Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=1157903&r1=1157902&r2=1157903&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java Mon Aug 15 16:36:07 2011
@@ -97,8 +97,7 @@ import org.apache.openjpa.util.UserExcep
  * @author Abe White
  * @nojavadoc
  */
-public class JDBCStoreManager 
-    implements StoreManager, JDBCStore {
+public class JDBCStoreManager implements StoreManager, JDBCStore {
 
     private static final Localizer _loc = Localizer.forPackage
         (JDBCStoreManager.class);
@@ -112,7 +111,8 @@ public class JDBCStoreManager 
     private RefCountConnection _conn = null;
     private boolean _active = false;
     private Log _log = null;
-
+    boolean _ignoreDfgForFkSelect = false;
+    
     // track the pending statements so we can cancel them
     private Set<Statement> _stmnts = Collections.synchronizedSet(new HashSet<Statement>());
 
@@ -1404,17 +1404,16 @@ public class JDBCStoreManager 
     }
 
     /**
-     * When selecting fieldes, a special case is made for mappings that use
-     * 2-part selects that aren't explicitly *not* in the dfg so that they
-     * can get their primary table data. This method tests for that special
-     * case as an optimization.
-     */
-    private boolean optSelect(FieldMapping fm, Select sel,
-        OpenJPAStateManager sm, JDBCFetchConfiguration fetch) {
-        return !fm.isInDefaultFetchGroup() 
-             && !fm.isDefaultFetchGroupExplicit()
-            && (sm == null || sm.getPCState() == PCState.TRANSIENT 
-            || !sm.getLoaded().get(fm.getIndex()))
+     * When selecting fields, a special case is made for mappings that use 2-part selects that aren't explicitly *not*
+     * in the dfg so that they can get their primary table data. This method tests for that special case as an
+     * optimization.
+     */
+    private boolean optSelect(FieldMapping fm, Select sel, OpenJPAStateManager sm, JDBCFetchConfiguration fetch) {
+        boolean dfg =
+            _ignoreDfgForFkSelect || 
+                !fm.isInDefaultFetchGroup() && !fm.isDefaultFetchGroupExplicit();
+
+        return dfg && (sm == null || sm.getPCState() == PCState.TRANSIENT || !sm.getLoaded().get(fm.getIndex()))
             && fm.supportsSelect(sel, Select.TYPE_TWO_PART, sm, this, fetch) > 0;
     }
 
@@ -1552,10 +1551,12 @@ public class JDBCStoreManager 
              ? getConfiguration().getFinderCacheInstance() : null;
     }
 
+    public void setIgnoreDfgForFkSelect(boolean b) {
+        _ignoreDfgForFkSelect = b;
+    }
 
     /**
-     * Connection returned to client code. Makes sure its wrapped connection
-     * ref count is decremented on finalize.
+     * Connection returned to client code. Makes sure its wrapped connection ref count is decremented on finalize.
      */
     public abstract static class ClientConnection extends
             DelegatingConnection {

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/OptSelectEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/OptSelectEntity.java?rev=1157903&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/OptSelectEntity.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/OptSelectEntity.java Mon Aug 15 16:36:07 2011
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.jdbc.kernel;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+import javax.persistence.Version;
+
+@Entity
+public class OptSelectEntity {
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    int id;
+
+    @Version
+    int version;
+
+    @OneToOne
+    OptSelectEntity eagerOneToOne;
+
+    @OneToOne(mappedBy = "eagerOneToOne")
+    OptSelectEntity eagerOneToOneOwner;
+
+    @OneToOne(fetch = FetchType.LAZY)
+    OptSelectEntity lazyOneToOne;
+
+    @OneToOne(mappedBy = "lazyOneToOne", fetch = FetchType.LAZY)
+    OptSelectEntity lazyOneToOneOwner;
+
+    public int getId() {
+        return id;
+    }
+
+    public OptSelectEntity getEagerOneToOne() {
+        return eagerOneToOne;
+    }
+
+    public void setEagerOneToOne(OptSelectEntity eagerOneToOne) {
+        this.eagerOneToOne = eagerOneToOne;
+    }
+
+    public OptSelectEntity getEagerOneToOneOwner() {
+        return eagerOneToOneOwner;
+    }
+
+    public void setEagerOneToOneOwner(OptSelectEntity eagerOneToOneOwner) {
+        this.eagerOneToOneOwner = eagerOneToOneOwner;
+    }
+
+    public OptSelectEntity getLazyOneToOne() {
+        return lazyOneToOne;
+    }
+
+    public void setLazyOneToOne(OptSelectEntity lazyOneToOne) {
+        this.lazyOneToOne = lazyOneToOne;
+    }
+
+    public OptSelectEntity getLazyOneToOneOwner() {
+        return lazyOneToOneOwner;
+    }
+
+    public void setLazyOneToOneOwner(OptSelectEntity lazyOneToOneOwner) {
+        this.lazyOneToOneOwner = lazyOneToOneOwner;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/OptSelectEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestJDBCStoreOptSelect.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestJDBCStoreOptSelect.java?rev=1157903&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestJDBCStoreOptSelect.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestJDBCStoreOptSelect.java Mon Aug 15 16:36:07 2011
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.jdbc.kernel;
+
+import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.kernel.StateManagerImpl;
+import org.apache.openjpa.kernel.StoreManager;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.persistence.EntityManagerImpl;
+import org.apache.openjpa.persistence.FetchPlan;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
+import org.apache.openjpa.persistence.test.SQLListenerTestCase;
+
+public class TestJDBCStoreOptSelect extends SQLListenerTestCase {
+    Object[] props = new Object[] { CLEAR_TABLES, OptSelectEntity.class };
+    OptSelectEntity e1, e2;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp(props);
+        createData();
+    }
+
+    public void test() {
+        OpenJPAEntityManagerSPI em = emf.createEntityManager();
+        StoreManager store = ((EntityManagerImpl) em).getBroker().getStoreManager().getDelegate();
+
+        FetchPlan fp = getFetchPlan(em);
+        try {
+            sql.clear();
+
+            if (store instanceof JDBCStoreManager == false) {
+                fail("StoreManager is not an instanceof JDBCStoreManager");
+            }
+            // Set this JDBCStoreManager property so that we will select FKs for fields that are in the DFG, but not
+            // included in the current select.
+            ((JDBCStoreManager) store).setIgnoreDfgForFkSelect(true);
+
+            // Remove all relationships
+            fp.removeField(OptSelectEntity.class, "eagerOneToOne");
+            fp.removeField(OptSelectEntity.class, "eagerOneToOneOwner");
+            fp.removeField(OptSelectEntity.class, "lazyOneToOne");
+            fp.removeField(OptSelectEntity.class, "lazyOneToOneOwner");
+
+            OptSelectEntity ee1 = em.find(OptSelectEntity.class, e1.getId());
+
+            // Make sure our sql has no joins
+            assertEquals(1, sql.size());
+            String s = sql.get(0);
+            assertFalse(s.contains("JOIN") && s.contains("join"));
+
+            // Check to see how many fks(intermediate fields) we selected.
+            StateManagerImpl smi = ((StateManagerImpl) ((PersistenceCapable) ee1).pcGetStateManager());
+            ClassMetaData cmd =
+                em.getConfiguration().getMetaDataRepositoryInstance().getMetaData(OptSelectEntity.class, null, true);
+            int fks = 0;
+            for (FieldMetaData fmd : cmd.getFields()) {
+                if (smi.getIntermediate(fmd.getIndex()) != null) {
+                    fks++;
+                }
+            }
+            assertEquals(2, fks);
+        } finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if (em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+
+    private FetchPlan getFetchPlan(OpenJPAEntityManagerSPI em) {
+        MetaDataRepository mdr = em.getConfiguration().getMetaDataRepositoryInstance();
+        FetchPlan fp = em.pushFetchPlan();
+        fp.removeFetchGroups(fp.getFetchGroups());
+        for (Class<?> cls : new Class<?>[] { OptSelectEntity.class }) {
+            ClassMetaData cmd = mdr.getMetaData(cls, null, true);
+            for (FieldMetaData fmd : cmd.getFields()) {
+                fp.addField(cls, fmd.getName());
+            }
+        }
+        return fp;
+    }
+
+    void createData() {
+        OpenJPAEntityManagerSPI em = emf.createEntityManager();
+        try {
+            em.getTransaction().begin();
+            e1 = new OptSelectEntity();
+            e2 = new OptSelectEntity();
+
+            e1.setEagerOneToOne(e2);
+            e2.setEagerOneToOneOwner(e2);
+
+            e1.setLazyOneToOne(e2);
+            e2.setLazyOneToOneOwner(e1);
+
+            em.persistAll(e1, e2);
+
+            em.getTransaction().commit();
+        } finally {
+            if (em.getTransaction().isActive())
+                em.getTransaction().rollback();
+            if (em.isOpen())
+                em.close();
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestJDBCStoreOptSelect.java
------------------------------------------------------------------------------
    svn:eol-style = native