You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2008/10/13 06:37:49 UTC

svn commit: r703912 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/ openjpa-per...

Author: fancy
Date: Sun Oct 12 21:37:48 2008
New Revision: 703912

URL: http://svn.apache.org/viewvc?rev=703912&view=rev
Log:
OPENJPA-744 OneToMany EAGER loading generates extra SQLs on inverse ManyToOne relation

Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/Publisher.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.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=703912&r1=703911&r2=703912&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 Sun Oct 12 21:37:48 2008
@@ -354,7 +354,11 @@
                     getMappedByFieldMapping();
                 Object mappedByObject = info.result.getMappedByValue();
                 if (mappedByFieldMapping != null && mappedByObject != null)
-                    setMappedBy(sm, mappedByFieldMapping, mappedByObject);
+                    if (mappedByObject instanceof OpenJPAId)
+                        sm.setIntermediate(mappedByFieldMapping.getIndex(),
+                            mappedByObject);
+                    else
+                        setMappedBy(sm, mappedByFieldMapping, mappedByObject);
             }
             // load the selected mappings into the given state manager
             if (res != null) {
@@ -914,9 +918,29 @@
         ConnectionInfo info = new ConnectionInfo();
         info.result = result;
         info.mapping = mapping;
+
+        // if inverse relation is known, exclude loading during find
+        exclude = excludeInverseRelation(mapping, info, exclude);
         return _ctx.find(oid, fetch, exclude, info, 0);
     }
 
+    private BitSet excludeInverseRelation(ClassMapping mapping,
+        ConnectionInfo info, BitSet exclude) {
+        FieldMapping inverse = info.result.getMappedByFieldMapping();
+        if (inverse != null) {
+            FieldMapping[] fms = mapping.getDefinedFieldMappings();
+            if (exclude == null)
+                exclude = new BitSet(fms.length);
+            for (int i = 0; i < fms.length; i++) {
+                if (fms[i] == inverse) {
+                    exclude.set(fms[i].getIndex());
+                    break;
+                }
+            }
+        }
+        return exclude;
+    }
+
     /**
      * Load the given state manager with data from the result set. Only
      * mappings originally selected will be loaded.

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=703912&r1=703911&r2=703912&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java Sun Oct 12 21:37:48 2008
@@ -312,8 +312,8 @@
             if (field.getOrderColumn() != null)
                 seq = res.getInt(field.getOrderColumn(), orderJoins) + 1;
 
-            // for inverseEager field
-            setMappedBy(oid, sm, coll, res);
+            // for inverse relation field
+            setMappedBy(oid, res);
             Object val = loadElement(null, store, fetch, res, dataJoins);
             add(store, coll, val);
         }
@@ -322,6 +322,23 @@
         return rels;
     }
 
+    private void setMappedBy(Object oid, Result res) {
+        //  for inverse toOne relation field
+        FieldMapping mappedByFieldMapping = field.getMappedByMapping();
+        
+        if (mappedByFieldMapping != null) {
+            ValueMapping val = mappedByFieldMapping.getValueMapping();
+            ClassMetaData decMeta = val.getTypeMetaData();
+            // this inverse field does not have corresponding classMapping
+            // its value may be a collection/map etc.
+            if (decMeta == null) 
+                return;
+            
+            res.setMappedByFieldMapping(mappedByFieldMapping);
+            res.setMappedByValue(oid);
+        }
+    }
+
     private void setMappedBy(Object oid, OpenJPAStateManager sm, Object coll,
         Result res) {
         // for inverseEager field

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/Publisher.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/Publisher.java?rev=703912&r1=703911&r2=703912&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/Publisher.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/Publisher.java Sun Oct 12 21:37:48 2008
@@ -21,6 +21,7 @@
 import java.io.Serializable;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
@@ -38,7 +39,7 @@
     @Column(name="name")
     private String name;
 
-    @OneToMany(mappedBy="idPublisher")
+    @OneToMany(mappedBy="idPublisher",  fetch=FetchType.EAGER)
     private Set<Magazine> magazineCollection;
 
 

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java?rev=703912&r1=703911&r2=703912&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java Sun Oct 12 21:37:48 2008
@@ -21,12 +21,16 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
 
 import junit.textui.TestRunner;
 import org.apache.openjpa.persistence.OpenJPAEntityManager;
 import org.apache.openjpa.persistence.OpenJPAQuery;
+import org.apache.openjpa.persistence.query.Magazine;
+import org.apache.openjpa.persistence.query.Publisher;
 import org.apache.openjpa.persistence.test.SQLListenerTestCase;
 
 
@@ -36,7 +40,8 @@
     public void setUp() {
         setUp(Customer.class, Customer.CustomerKey.class, Order.class, 
         	EntityAInverseEager.class, EntityA1InverseEager.class, EntityA2InverseEager.class, 
-        	EntityBInverseEager.class, EntityCInverseEager.class, EntityDInverseEager.class);
+        	EntityBInverseEager.class, EntityCInverseEager.class, EntityDInverseEager.class,
+            Publisher.class, Magazine.class);
         
         EntityManager em = emf.createEntityManager();
         em.getTransaction().begin();
@@ -93,7 +98,29 @@
             c1.setD(d1);
             d1.setC(c1);
         }
-        
+
+        Publisher p1 = new Publisher();
+        p1.setName("publisher1");
+        em.persist(p1);
+   
+        for (int i = 0; i < 4; i++) {
+            Magazine magazine = new Magazine();
+            magazine.setIdPublisher(p1);
+            magazine.setName("magagine"+i+"_"+p1.getName());
+            em.persist(magazine);
+        }
+
+        Publisher p2 = new Publisher();
+        p2.setName("publisher2");
+        em.persist(p2);
+   
+        for (int i = 0; i < 4; i++) {
+            Magazine magazine = new Magazine();
+            magazine.setIdPublisher(p2);
+            magazine.setName("magagine"+i+"_"+p2.getName());
+            em.persist(magazine);
+        }
+
         em.flush();
         em.getTransaction().commit();
         em.close();
@@ -197,6 +224,32 @@
         em.close();
     }
 
+    public void testOneToManyEagerInverseLazyQuery() {
+        sql.clear();
+
+        OpenJPAEntityManager em = emf.createEntityManager();
+        String query = "select p FROM Publisher p";
+        Query q = em.createQuery(query);
+        List list = q.getResultList();
+        assertEquals(2, list.size());
+        assertEquals(2, sql.size());
+
+        sql.clear();
+        for (int i = 0; i < list.size(); i++) {
+            Publisher p = (Publisher) list.get(i);
+            Set<Magazine> magazines = p.getMagazineCollection();
+            assertEquals(4, magazines.size());
+            for (Iterator iter = magazines.iterator(); iter.hasNext();) {
+                Magazine m = (Magazine) iter.next();
+                Publisher mp = m.getIdPublisher();
+                assertEquals(p, mp);
+            }
+        }
+
+        assertEquals(0, sql.size());
+        em.close();
+    }
+
     public static void main(String[] args) {
         TestRunner.run(TestInverseEagerSQL.class);
     }