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,7 +354,11 @@ public class JDBCStoreManager
|
||||||
getMappedByFieldMapping();
|
getMappedByFieldMapping();
|
||||||
Object mappedByObject = info.result.getMappedByValue();
|
Object mappedByObject = info.result.getMappedByValue();
|
||||||
if (mappedByFieldMapping != null && mappedByObject != null)
|
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
|
// load the selected mappings into the given state manager
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
|
@ -914,9 +918,29 @@ public class JDBCStoreManager
|
||||||
ConnectionInfo info = new ConnectionInfo();
|
ConnectionInfo info = new ConnectionInfo();
|
||||||
info.result = result;
|
info.result = result;
|
||||||
info.mapping = mapping;
|
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);
|
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
|
* Load the given state manager with data from the result set. Only
|
||||||
* mappings originally selected will be loaded.
|
* mappings originally selected will be loaded.
|
||||||
|
|
|
@ -312,8 +312,8 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
if (field.getOrderColumn() != null)
|
if (field.getOrderColumn() != null)
|
||||||
seq = res.getInt(field.getOrderColumn(), orderJoins) + 1;
|
seq = res.getInt(field.getOrderColumn(), orderJoins) + 1;
|
||||||
|
|
||||||
// for inverseEager field
|
// for inverse relation field
|
||||||
setMappedBy(oid, sm, coll, res);
|
setMappedBy(oid, res);
|
||||||
Object val = loadElement(null, store, fetch, res, dataJoins);
|
Object val = loadElement(null, store, fetch, res, dataJoins);
|
||||||
add(store, coll, val);
|
add(store, coll, val);
|
||||||
}
|
}
|
||||||
|
@ -322,6 +322,23 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
return rels;
|
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,
|
private void setMappedBy(Object oid, OpenJPAStateManager sm, Object coll,
|
||||||
Result res) {
|
Result res) {
|
||||||
// for inverseEager field
|
// for inverseEager field
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.apache.openjpa.persistence.query;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.GenerationType;
|
import javax.persistence.GenerationType;
|
||||||
|
@ -38,7 +39,7 @@ public class Publisher implements Serializable {
|
||||||
@Column(name="name")
|
@Column(name="name")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@OneToMany(mappedBy="idPublisher")
|
@OneToMany(mappedBy="idPublisher", fetch=FetchType.EAGER)
|
||||||
private Set<Magazine> magazineCollection;
|
private Set<Magazine> magazineCollection;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,16 @@ package org.apache.openjpa.persistence.relations;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
import junit.textui.TestRunner;
|
import junit.textui.TestRunner;
|
||||||
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||||
import org.apache.openjpa.persistence.OpenJPAQuery;
|
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;
|
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +40,8 @@ public class TestInverseEagerSQL
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
setUp(Customer.class, Customer.CustomerKey.class, Order.class,
|
setUp(Customer.class, Customer.CustomerKey.class, Order.class,
|
||||||
EntityAInverseEager.class, EntityA1InverseEager.class, EntityA2InverseEager.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();
|
EntityManager em = emf.createEntityManager();
|
||||||
em.getTransaction().begin();
|
em.getTransaction().begin();
|
||||||
|
@ -93,7 +98,29 @@ public class TestInverseEagerSQL
|
||||||
c1.setD(d1);
|
c1.setD(d1);
|
||||||
d1.setC(c1);
|
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.flush();
|
||||||
em.getTransaction().commit();
|
em.getTransaction().commit();
|
||||||
em.close();
|
em.close();
|
||||||
|
@ -197,6 +224,32 @@ public class TestInverseEagerSQL
|
||||||
em.close();
|
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) {
|
public static void main(String[] args) {
|
||||||
TestRunner.run(TestInverseEagerSQL.class);
|
TestRunner.run(TestInverseEagerSQL.class);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue