mirror of https://github.com/apache/openjpa.git
OPENJPA-241 Extra SQL on lazy CMR load
commit openjpa_241.patch on behalf of Fay Wang git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@678828 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b4c557d0c0
commit
8cfa25c524
|
@ -349,6 +349,13 @@ public class JDBCStoreManager
|
||||||
// from the indicator is a subclass of expected type
|
// from the indicator is a subclass of expected type
|
||||||
sm.initialize(type, state);
|
sm.initialize(type, state);
|
||||||
|
|
||||||
|
if (info != null && info.result != null) {
|
||||||
|
FieldMapping mappedByFieldMapping = info.result.
|
||||||
|
getMappedByFieldMapping();
|
||||||
|
Object mappedByObject = info.result.getMappedByValue();
|
||||||
|
if (mappedByFieldMapping != null && mappedByObject != null)
|
||||||
|
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) {
|
||||||
// re-get the mapping in case the instance was a subclass
|
// re-get the mapping in case the instance was a subclass
|
||||||
|
@ -362,7 +369,19 @@ public class JDBCStoreManager
|
||||||
res.close();
|
res.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setMappedBy(OpenJPAStateManager sm,
|
||||||
|
FieldMapping mappedByFieldMapping, Object mappedByObject) {
|
||||||
|
ClassMapping mapping = (ClassMapping) sm.getMetaData();
|
||||||
|
FieldMapping[] fms = mapping.getDeclaredFieldMappings();
|
||||||
|
for (int i = 0; i < fms.length; i++) {
|
||||||
|
if (fms[i] == mappedByFieldMapping) {
|
||||||
|
sm.storeObject(fms[i].getIndex(), mappedByObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is to provide override for non-JDBC or JDBC-like
|
* This method is to provide override for non-JDBC or JDBC-like
|
||||||
* implementation of getting version from the result set.
|
* implementation of getting version from the result set.
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.openjpa.enhance.PersistenceCapable;
|
||||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfigurationImpl;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfigurationImpl;
|
||||||
|
@ -33,12 +34,12 @@ import org.apache.openjpa.jdbc.kernel.JDBCStoreManager;
|
||||||
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||||
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
||||||
import org.apache.openjpa.jdbc.meta.FieldStrategy;
|
import org.apache.openjpa.jdbc.meta.FieldStrategy;
|
||||||
|
import org.apache.openjpa.jdbc.meta.ValueMapping;
|
||||||
import org.apache.openjpa.jdbc.schema.Column;
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
import org.apache.openjpa.jdbc.schema.ForeignKey;
|
import org.apache.openjpa.jdbc.schema.ForeignKey;
|
||||||
import org.apache.openjpa.jdbc.sql.Joins;
|
import org.apache.openjpa.jdbc.sql.Joins;
|
||||||
import org.apache.openjpa.jdbc.sql.LogicalUnion;
|
import org.apache.openjpa.jdbc.sql.LogicalUnion;
|
||||||
import org.apache.openjpa.jdbc.sql.Result;
|
import org.apache.openjpa.jdbc.sql.Result;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.jdbc.sql.SelectExecutor;
|
import org.apache.openjpa.jdbc.sql.SelectExecutor;
|
||||||
import org.apache.openjpa.jdbc.sql.SelectImpl;
|
import org.apache.openjpa.jdbc.sql.SelectImpl;
|
||||||
|
@ -46,6 +47,7 @@ import org.apache.openjpa.jdbc.sql.Union;
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.lib.log.Log;
|
import org.apache.openjpa.lib.log.Log;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.JavaTypes;
|
import org.apache.openjpa.meta.JavaTypes;
|
||||||
import org.apache.openjpa.util.ChangeTracker;
|
import org.apache.openjpa.util.ChangeTracker;
|
||||||
import org.apache.openjpa.util.Id;
|
import org.apache.openjpa.util.Id;
|
||||||
|
@ -305,13 +307,61 @@ 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;
|
||||||
add(store, coll, loadElement(null, store, fetch, res, dataJoins));
|
|
||||||
|
// for inverseEager field
|
||||||
|
setMappedBy(oid, sm, coll, res);
|
||||||
|
Object val = loadElement(null, store, fetch, res, dataJoins);
|
||||||
|
add(store, coll, val);
|
||||||
}
|
}
|
||||||
res.close();
|
res.close();
|
||||||
|
|
||||||
return rels;
|
return rels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setMappedBy(Object oid, OpenJPAStateManager sm, Object coll,
|
||||||
|
Result res) {
|
||||||
|
// for inverseEager field
|
||||||
|
FieldMapping mappedByFieldMapping = field.getMappedByMapping();
|
||||||
|
PersistenceCapable mappedByValue = null;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (oid.equals(sm.getObjectId())) {
|
||||||
|
mappedByValue = sm.getPersistenceCapable();
|
||||||
|
res.setMappedByFieldMapping(mappedByFieldMapping);
|
||||||
|
res.setMappedByValue(mappedByValue);
|
||||||
|
} else if (coll instanceof Collection &&
|
||||||
|
((Collection) coll).size() > 0) {
|
||||||
|
// Customer (1) <--> Orders(n)
|
||||||
|
// coll contains the values of the toMany field (Orders)
|
||||||
|
// get the StateManager of this toMany value
|
||||||
|
// and find the value of the inverse mappedBy field (Customer)
|
||||||
|
// for this toMacdny field
|
||||||
|
PersistenceCapable pc = (PersistenceCapable)
|
||||||
|
((Collection) coll).iterator().next();
|
||||||
|
OpenJPAStateManager sm1 = (OpenJPAStateManager) pc.
|
||||||
|
pcGetStateManager();
|
||||||
|
FieldMapping[] fms = ((ClassMapping) sm1.getMetaData()).
|
||||||
|
getDeclaredFieldMappings();
|
||||||
|
for (int i = 0; i < fms.length; i++) {
|
||||||
|
if (fms[i] == mappedByFieldMapping) {
|
||||||
|
res.setMappedByValue(sm1.fetchObject(fms[i].
|
||||||
|
getIndex()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.setMappedByValue(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the oid value from the given result. If the next oid is the
|
* Extract the oid value from the given result. If the next oid is the
|
||||||
* same as the given one, returns the given JVM instance.
|
* same as the given one, returns the given JVM instance.
|
||||||
|
@ -555,6 +605,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
while (res.next()) {
|
while (res.next()) {
|
||||||
if (ct != null && field.getOrderColumn() != null)
|
if (ct != null && field.getOrderColumn() != null)
|
||||||
seq = res.getInt(field.getOrderColumn());
|
seq = res.getInt(field.getOrderColumn());
|
||||||
|
setMappedBy(sm.getObjectId(), sm, coll, res);
|
||||||
add(store, coll, loadElement(sm, store, fetch, res,
|
add(store, coll, loadElement(sm, store, fetch, res,
|
||||||
resJoins[res.indexOf()]));
|
resJoins[res.indexOf()]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,8 @@ public abstract class AbstractResult
|
||||||
private boolean _locking = false;
|
private boolean _locking = false;
|
||||||
private boolean _ignoreNext = false;
|
private boolean _ignoreNext = false;
|
||||||
private boolean _last = false;
|
private boolean _last = false;
|
||||||
|
private FieldMapping _mappedByFieldMapping = null;
|
||||||
|
private Object _mappedByValue = null;
|
||||||
|
|
||||||
public Object getEager(FieldMapping key) {
|
public Object getEager(FieldMapping key) {
|
||||||
Map map = getEagerMap(true);
|
Map map = getEagerMap(true);
|
||||||
|
@ -118,6 +120,8 @@ public abstract class AbstractResult
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
closeEagerMap(_eager);
|
closeEagerMap(_eager);
|
||||||
|
_mappedByFieldMapping = null;
|
||||||
|
_mappedByValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -238,6 +242,22 @@ public abstract class AbstractResult
|
||||||
_base = base;
|
_base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FieldMapping getMappedByFieldMapping() {
|
||||||
|
return (_gotEager) ? null : _mappedByFieldMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappedByFieldMapping(FieldMapping fieldMapping) {
|
||||||
|
_mappedByFieldMapping = fieldMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getMappedByValue() {
|
||||||
|
return (_gotEager) ? null : _mappedByValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappedByValue(Object mappedByValue) {
|
||||||
|
_mappedByValue = mappedByValue;
|
||||||
|
}
|
||||||
|
|
||||||
public int indexOf() {
|
public int indexOf() {
|
||||||
return _index;
|
return _index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,22 @@ public class MergedResult
|
||||||
_res[_idx].setBaseMapping(mapping);
|
_res[_idx].setBaseMapping(mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FieldMapping getMappedByFieldMapping() {
|
||||||
|
return _res[_idx].getMappedByFieldMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappedByFieldMapping(FieldMapping fieldMapping) {
|
||||||
|
_res[_idx].setMappedByFieldMapping(fieldMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getMappedByValue() {
|
||||||
|
return _res[_idx].getMappedByValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappedByValue(Object mappedByValue) {
|
||||||
|
_res[_idx].setMappedByValue(mappedByValue);
|
||||||
|
}
|
||||||
|
|
||||||
public int indexOf() {
|
public int indexOf() {
|
||||||
return _res[_idx].indexOf();
|
return _res[_idx].indexOf();
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,36 @@ public interface Result
|
||||||
*/
|
*/
|
||||||
public void setBaseMapping(ClassMapping mapping);
|
public void setBaseMapping(ClassMapping mapping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is the result used to select a toMany relationship,
|
||||||
|
* the mappedByFieldMapping is field mapping representing
|
||||||
|
* the inverse relationship. This is to avoid unneeded
|
||||||
|
* extra sql to retrieve the eager inverse field.
|
||||||
|
*/
|
||||||
|
public FieldMapping getMappedByFieldMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is the result used to select a toMany relationship,
|
||||||
|
* the mappedByFieldMapping is field mapping representing
|
||||||
|
* the inverse relationship. This is to avoid unneeded
|
||||||
|
* extra sql to retrieve the eager inverse field.
|
||||||
|
*/
|
||||||
|
public void setMappedByFieldMapping(FieldMapping fieldMapping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is the result used to select a toMany relationship,
|
||||||
|
* the mappedByValue is value of the owner of the toMany relationship.
|
||||||
|
* This is to avoid unneeded extra sql to retrieve the eager inverse field.
|
||||||
|
*/
|
||||||
|
public Object getMappedByValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is the result used to select a toMany relationship,
|
||||||
|
* the mappedByValue is value of the owner of the toMany relationship.
|
||||||
|
* This is to avoid unneeded extra sql to retrieve the eager inverse field.
|
||||||
|
*/
|
||||||
|
public void setMappedByValue(Object mappedByValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index of the select within the UNION that the current row
|
* The index of the select within the UNION that the current row
|
||||||
* corresponds to, or 0.
|
* corresponds to, or 0.
|
||||||
|
|
Loading…
Reference in New Issue