OPENJPA-744 OneToMany EAGER loading generates extra SQLs on inverse ManyToOne relation

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@703912 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Catalina Wei 2008-10-13 04:37:48 +00:00
parent 99dc9d8a66
commit 212ddcefc9
4 changed files with 101 additions and 6 deletions

View File

@ -354,7 +354,11 @@ public class JDBCStoreManager
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 @@ public class JDBCStoreManager
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.

View File

@ -312,8 +312,8 @@ public abstract class StoreCollectionFieldStrategy
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 @@ public abstract class StoreCollectionFieldStrategy
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

View File

@ -21,6 +21,7 @@ package org.apache.openjpa.persistence.query;
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 @@ public class Publisher implements Serializable {
@Column(name="name")
private String name;
@OneToMany(mappedBy="idPublisher")
@OneToMany(mappedBy="idPublisher", fetch=FetchType.EAGER)
private Set<Magazine> magazineCollection;

View File

@ -21,12 +21,16 @@ package org.apache.openjpa.persistence.relations;
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 class TestInverseEagerSQL
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();
@ -94,6 +99,28 @@ public class TestInverseEagerSQL
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 @@ public class TestInverseEagerSQL
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);
}