mirror of https://github.com/apache/openjpa.git
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:
parent
99dc9d8a66
commit
212ddcefc9
|
@ -354,6 +354,10 @@ public class JDBCStoreManager
|
|||
getMappedByFieldMapping();
|
||||
Object mappedByObject = info.result.getMappedByValue();
|
||||
if (mappedByFieldMapping != null && mappedByObject != null)
|
||||
if (mappedByObject instanceof OpenJPAId)
|
||||
sm.setIntermediate(mappedByFieldMapping.getIndex(),
|
||||
mappedByObject);
|
||||
else
|
||||
setMappedBy(sm, mappedByFieldMapping, mappedByObject);
|
||||
}
|
||||
// load the selected mappings into the given state manager
|
||||
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue