You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ol...@apache.org on 2003/08/25 21:28:27 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/otm/util IdentityHashMap.java IdentityMapFactory.java
olegnitz 2003/08/25 12:28:27
Modified: src/java/org/apache/ojb/broker/accesslayer
CollectionPrefetcher.java ReferencePrefetcher.java
RelationshipPrefetcherImpl.java RsIterator.java
src/java/org/apache/ojb/broker/core
PersistenceBrokerImpl.java
src/java/org/apache/ojb/otm/copy
MetadataObjectCopyStrategy.java
ReflectiveObjectCopyStrategy.java
Added: src/java/org/apache/ojb/broker/util IdentityHashMap.java
IdentityMapFactory.java
Removed: src/java/org/apache/ojb/otm/util IdentityHashMap.java
IdentityMapFactory.java
Log:
Optimization of retriaval operations via gathering them into batches, see details in the ojb-dev mailing list
Revision Changes Path
1.14 +104 -46 db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java
Index: CollectionPrefetcher.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- CollectionPrefetcher.java 24 May 2003 23:58:20 -0000 1.13
+++ CollectionPrefetcher.java 25 Aug 2003 19:28:27 -0000 1.14
@@ -54,11 +54,15 @@
* <http://www.apache.org/>.
*/
+import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.HashMap;
import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.ManageableCollection;
+import org.apache.ojb.broker.OJBRuntimeException;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.metadata.ClassDescriptor;
@@ -71,6 +75,7 @@
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.QueryFactory;
+import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
/**
* Relationship Prefetcher for Collections.
@@ -92,6 +97,34 @@
}
/**
+ * Build the multiple queries for one relationship because of limitation of IN(...)
+ * @param owners Collection containing all objects of the ONE side
+ */
+ protected Query[] buildPrefetchQueries(Collection owners)
+ {
+ Collection queries = new ArrayList();
+ Collection ownerSubset = new ArrayList();
+ Iterator iter = owners.iterator();
+
+ while (iter.hasNext())
+ {
+ ownerSubset.add(iter.next());
+ if (ownerSubset.size() == pkLimit)
+ {
+ queries.add(buildPrefetchQuery(ownerSubset));
+ ownerSubset.clear();
+ }
+ }
+
+ if (ownerSubset.size() > 0)
+ {
+ queries.add(buildPrefetchQuery(ownerSubset));
+ }
+
+ return (Query[]) queries.toArray(new Query[queries.size()]);
+ }
+
+ /**
* Build the query to perform a batched read get orderBy settings from
* CollectionDescriptor
* @param owners Collection containing all objects of the ONE side
@@ -136,7 +169,7 @@
private Criteria buildPrefetchCriteriaSingleKey(Collection owners, FieldDescriptor fkField)
{
Criteria crit = new Criteria();
- Collection pkValues = new ArrayList();
+ ArrayList pkValues = new ArrayList();
Iterator iter = owners.iterator();
Object pkVal;
Object owner;
@@ -149,10 +182,17 @@
pkValues.add(pkVal);
}
- // create IN (...) for the single key field
- if (!pkValues.isEmpty())
+ switch (pkValues.size())
{
- crit.addIn(fkField.getAttributeName(), pkValues);
+ case 0:
+ break;
+ case 1:
+ crit.addEqualTo(fkField.getAttributeName(), pkValues.get(0));
+ break;
+ default:
+ // create IN (...) for the single key field
+ crit.addIn(fkField.getAttributeName(), pkValues);
+ break;
}
return crit;
@@ -196,69 +236,87 @@
*/
protected void associateBatched(Collection owners, Collection children)
{
+ CollectionDescriptor cds = getCollectionDescriptor();
ClassDescriptor cld = getItemClassDescriptor();
Iterator iter = children.iterator();
- PersistentField field = getObjectReferenceDescriptor().getPersistentField();
- Class ownerClass = getBroker().getTopLevelClass(getOwnerClassDescriptor().getClassOfObject());
+ PersistentField field = cds.getPersistentField();
+ PersistenceBroker pb = getBroker();
+ ClassDescriptor ownerCld = getOwnerClassDescriptor();
+ Class ownerClass = pb.getTopLevelClass(ownerCld.getClassOfObject());
+ // this collection type will be used:
+ Class collectionClass = cds.getCollectionClass();
Object owner, relatedObject;
Object fkValues[];
Identity id;
+ HashMap ownerIdsToLists = new HashMap();
+ ArrayList list;
+ Object result;
+
+ // ensure that all owners will get non-null collections
+ iter = owners.iterator();
+ while (iter.hasNext())
+ {
+ id = new Identity(iter.next(), pb);
+ ownerIdsToLists.put(id, new ArrayList());
+ }
+ iter = children.iterator();
while (iter.hasNext())
{
relatedObject = iter.next();
- fkValues = getObjectReferenceDescriptor().getForeignKeyValues(relatedObject, cld);
- id = new Identity(getOwnerClassDescriptor().getClassOfObject(), ownerClass, fkValues);
- owner = getBroker().getObjectByIdentity(id);
+ fkValues = cds.getForeignKeyValues(relatedObject, cld);
+ id = new Identity(ownerCld.getClassOfObject(), ownerClass, fkValues);
+ list = (ArrayList) ownerIdsToLists.get(id);
+
+ // BRJ: do not add object if it's already in the list
+ if (!list.contains(relatedObject))
+ {
+ list.add(relatedObject);
+ }
+ }
- if (Collection.class.isAssignableFrom(field.getType()))
+ for (Iterator it = ownerIdsToLists.keySet().iterator(); it.hasNext(); )
+ {
+ id = (Identity) it.next();
+ list = (ArrayList) ownerIdsToLists.get(id);
+ owner = pb.getObjectByIdentity(id);
+ if ((collectionClass == null)
+ && field.getType().isArray())
{
- Collection relatedData = (Collection) field.get(owner);
- if (relatedData == null)
+ int length = list.size();
+ Class itemtype = field.getType().getComponentType();
+ result = Array.newInstance(itemtype, length);
+ for (int j = 0; j < length; j++)
+ {
+ Array.set(result, j, list.get(j));
+ }
+ }
+ else
+ {
+ ManageableCollection col;
+
+ if (collectionClass == null)
+ {
+ col = new RemovalAwareCollection();
+ }
+ else
{
try
{
- // instantiate and set the owners collection
- relatedData = (Collection) children.getClass().newInstance();
- field.set(owner, relatedData);
+ col = (ManageableCollection) collectionClass.newInstance();
}
catch (Exception e)
{
- getLogger().error("Can't create new Collection for owner", e);
+ throw new OJBRuntimeException("Can't create new Collection for owner", e);
}
}
-
- // BRJ: do not add object if it's already in the list
- if (!relatedData.contains(relatedObject))
+ for (Iterator it2 = list.iterator(); it2.hasNext(); )
{
- relatedData.add(relatedObject);
+ col.ojbAdd(it2.next());
}
+ result = col;
}
- else
- {
- getLogger().error("Prefetch works with Collections only");
- }
- }
- }
-
- /**
- * @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcher#prefetchRelationship(Collection)
- */
- public void prefetchRelationship(Collection owners)
- {
- PersistentField f = getObjectReferenceDescriptor().getPersistentField();
-
- if (f.getType().isArray())
- {
- throw new PersistenceBrokerException("Prefetch does not yet work with Arrays: '" + f.getName() + "'");
- }
- if (getCollectionDescriptor().isLazy())
- {
- getLogger().warn("Prefetching a proxied collection does not make sense: '" + f.getName() + "'");
- }
- else
- {
- super.prefetchRelationship(owners);
+ field.set(owner, result);
}
}
1.6 +61 -17 db-ojb/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java
Index: ReferencePrefetcher.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ReferencePrefetcher.java 24 May 2003 23:58:20 -0000 1.5
+++ ReferencePrefetcher.java 25 Aug 2003 19:28:27 -0000 1.6
@@ -56,10 +56,12 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.cache.ObjectCache;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
@@ -112,10 +114,52 @@
}
}
- /**
+ /**
+ * Build the multiple queries for one relationship because of limitation of IN(...)
+ * @param owners Collection containing all objects of the ONE side
+ */
+ protected Query[] buildPrefetchQueries(Collection owners)
+ {
+ ClassDescriptor cld = getOwnerClassDescriptor();
+ ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
+ Collection queries = new ArrayList();
+ Collection idsSubset = new HashSet();
+ Iterator iter = owners.iterator();
+ Class topLevelClass = getBroker().getTopLevelClass(ord.getItemClass());
+ Class realClass = ord.getItemClass();
+ Object[] fkValues;
+ Object owner;
+ Identity id;
+ ObjectCache cache = getBroker().serviceObjectCache();
+
+ while (iter.hasNext())
+ {
+ owner = iter.next();
+ fkValues = ord.getForeignKeyValues(owner,cld);
+ id = new Identity(realClass, topLevelClass, fkValues);
+ if (cache.lookup(id) == null)
+ {
+ idsSubset.add(id);
+ }
+ if (idsSubset.size() == pkLimit)
+ {
+ queries.add(buildPrefetchQuery(idsSubset));
+ idsSubset.clear();
+ }
+ }
+
+ if (idsSubset.size() > 0)
+ {
+ queries.add(buildPrefetchQuery(idsSubset));
+ }
+
+ return (Query[]) queries.toArray(new Query[queries.size()]);
+ }
+
+ /**
* @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcherImpl#buildPrefetchQuery(Collection)
*/
- protected Query buildPrefetchQuery(Collection owners)
+ protected Query buildPrefetchQuery(Collection ids)
{
ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
FieldDescriptor pkFields[] = getItemClassDescriptor().getPkFields();
@@ -123,11 +167,11 @@
if (pkFields.length == 1)
{
- crit = buildPrefetchCriteriaSingleKey(owners, pkFields[0]);
+ crit = buildPrefetchCriteriaSingleKey(ids, pkFields[0]);
}
else
{
- crit = buildPrefetchCriteriaMultipleKeys(owners, pkFields);
+ crit = buildPrefetchCriteriaMultipleKeys(ids, pkFields);
}
return QueryFactory.newQuery(ord.getItemClass(), crit);
@@ -135,22 +179,22 @@
/**
* Build the Criteria using IN(...) for single keys
- * @param owners
+ * @param ids
* @param pkField
* @return Criteria
*/
- private Criteria buildPrefetchCriteriaSingleKey(Collection owners, FieldDescriptor pkField)
+ private Criteria buildPrefetchCriteriaSingleKey(Collection ids, FieldDescriptor pkField)
{
Criteria crit = new Criteria();
Collection fkValues = new ArrayList();
- Iterator iter = owners.iterator();
+ Iterator iter = ids.iterator();
+ Identity id;
Object fkVal;
- Object owner;
while (iter.hasNext())
{
- owner = iter.next();
- fkVal = getObjectReferenceDescriptor().getForeignKeyValues(owner, getOwnerClassDescriptor())[0];
+ id = (Identity) iter.next();
+ fkVal = id.getPrimaryKeyValues()[0];
if (fkVal != null)
{
fkValues.add(fkVal);
@@ -168,22 +212,22 @@
/**
* Build the Criteria using multiple ORs
- * @param owners
+ * @param ids
* @param pkFields
* @return Criteria
*/
- private Criteria buildPrefetchCriteriaMultipleKeys(Collection owners, FieldDescriptor pkFields[])
+ private Criteria buildPrefetchCriteriaMultipleKeys(Collection ids, FieldDescriptor pkFields[])
{
Criteria crit = new Criteria();
- Iterator iter = owners.iterator();
+ Iterator iter = ids.iterator();
Object[] fkVal;
- Object owner;
+ Identity id;
while (iter.hasNext())
{
Criteria c = new Criteria();
- owner = iter.next();
- fkVal = getObjectReferenceDescriptor().getForeignKeyValues(owner, getOwnerClassDescriptor());
+ id = (Identity) iter.next();
+ fkVal = id.getPrimaryKeyValues();
for (int i=0;i < fkVal.length;i++)
{
if (fkVal[i] != null)
1.5 +20 -48 db-ojb/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java
Index: RelationshipPrefetcherImpl.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- RelationshipPrefetcherImpl.java 26 Apr 2003 23:18:25 -0000 1.4
+++ RelationshipPrefetcherImpl.java 25 Aug 2003 19:28:27 -0000 1.5
@@ -82,6 +82,7 @@
private PersistenceBroker broker;
private ObjectReferenceDescriptor objectReferenceDescriptor;
private boolean cascadeRetrieve;
+ protected final int pkLimit; // max number of pk's in one query
protected static final int IN_LIMIT = getPrefetchInLimit();
@@ -110,7 +111,7 @@
setBroker(aBroker);
setObjectReferenceDescriptor(anOrd);
setLogger(LoggerFactory.getLogger(this.getClass()));
-
+ pkLimit = getPrefetchInLimit() / getItemClassDescriptor().getPkFields().length;
}
/**
@@ -127,23 +128,22 @@
*/
protected abstract void associateBatched(Collection owners, Collection children);
- /**
- * @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcher#prefetchRelationship(Collection)
- */
- public void prefetchRelationship(Collection owners)
- {
- Query queries[];
- Collection children;
-
- queries = buildPrefetchQueries(owners, IN_LIMIT);
-
- for (int i = 0; i < queries.length; i++)
- {
- children = getBroker().getCollectionByQuery(queries[i]);
- associateBatched(owners, children);
- }
-
- }
+ /**
+ * @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcher#prefetchRelationship(Collection)
+ */
+ public void prefetchRelationship(Collection owners)
+ {
+ Query queries[];
+ Collection children = new ArrayList();
+
+ queries = buildPrefetchQueries(owners);
+
+ for (int i = 0; i < queries.length; i++)
+ {
+ children.addAll(getBroker().getCollectionByQuery(queries[i]));
+ }
+ associateBatched(owners, children);
+ }
/**
* Return the DescriptorRepository
@@ -171,35 +171,7 @@
return getDescriptorRepository().getDescriptorFor(getObjectReferenceDescriptor().getItemClass());
}
- /**
- * Build the query (using IN(...) )to perform a batched read
- * @param owners Collection containing all objects of the ONE side
- */
- protected abstract Query buildPrefetchQuery(Collection owners);
-
- /**
- * Build the multiple queries for one relationship because of limitation of IN(...)
- * @param owners Collection containing all objects of the ONE side
- * @param inLimit the max number of values of IN(), -1 is unlimited
- */
- protected Query[] buildPrefetchQueries(Collection owners, int inLimit)
- {
- Collection queries = new ArrayList();
- Collection ownerSubset = new ArrayList();
- Iterator iter = owners.iterator();
-
- while (iter.hasNext())
- {
- ownerSubset.add(iter.next());
- if (ownerSubset.size() == inLimit || !iter.hasNext())
- {
- queries.add(buildPrefetchQuery(ownerSubset));
- ownerSubset = new ArrayList();
- }
- }
-
- return (Query[]) queries.toArray(new Query[queries.size()]);
- }
+ protected abstract Query[] buildPrefetchQueries(Collection owners);
/**
* @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcher#restoreRelationshipSettings()
1.42 +20 -3 db-ojb/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
Index: RsIterator.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- RsIterator.java 3 Aug 2003 09:26:36 -0000 1.41
+++ RsIterator.java 25 Aug 2003 19:28:27 -0000 1.42
@@ -155,6 +155,17 @@
* return value of the previously called hasNext from m_rs
*/
protected boolean hasNext = false;
+
+ /**
+ * This is the place to add retrieval tasks that are grouped by
+ * ObjectReferenceDescriptors (keys) which are mapped to
+ * IdentityHashMaps mapping owner objects to itself (~IdentityHashSet).
+ * After thit Iterator will be traversed, all the tasks will
+ * be performed: related objects for the gathered owners will
+ * be loaded and set as values of respective fields of owners.
+ */
+ protected HashMap m_retrievalTasks;
+
private boolean advancedJDBCSupport = false;
private boolean JDBCSupportAssessed = false;
private Query m_query = null;
@@ -277,6 +288,11 @@
{
throw new UnsupportedOperationException("removing not supported by RsIterator");
}
+
+ public void setRetrievalTasks(HashMap retrievalTasks)
+ {
+ m_retrievalTasks = retrievalTasks;
+ }
/**
* read all objects of this iterator. objects will be placed in cache
@@ -446,8 +462,9 @@
ClassDescriptor cld = m_cld.getRepository().getDescriptorFor(result.getClass());
// don't force loading of reference
final boolean unforced = false;
- m_broker.retrieveReferences(result, cld, unforced);
- m_broker.retrieveCollections(result, cld, unforced);
+ // Maps ReferenceDescriptors to HashSets of owners
+ m_broker.retrieveReferences(result, cld, unforced, m_retrievalTasks);
+ m_broker.retrieveCollections(result, cld, unforced, m_retrievalTasks);
}
}
}
1.33 +126 -50 db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
Index: PersistenceBrokerImpl.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- PersistenceBrokerImpl.java 11 Aug 2003 22:54:51 -0000 1.32
+++ PersistenceBrokerImpl.java 25 Aug 2003 19:28:27 -0000 1.33
@@ -59,7 +59,9 @@
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Vector;
import org.apache.ojb.broker.*;
@@ -88,6 +90,7 @@
import org.apache.ojb.broker.query.ReportQueryByMtoNCriteria;
import org.apache.ojb.broker.util.ArrayIterator;
import org.apache.ojb.broker.util.BrokerHelper;
+import org.apache.ojb.broker.util.IdentityMapFactory;
import org.apache.ojb.broker.util.ObjectModification;
import org.apache.ojb.broker.util.ProxyHelper;
import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
@@ -124,6 +127,8 @@
{
private Logger logger = LoggerFactory.getLogger(PersistenceBrokerImpl.class);
+ private boolean autoPrefetch = true;
+
protected PersistenceBrokerFactoryIF pbf;
/**
@@ -991,8 +996,20 @@
ClassDescriptor cld = descriptorRepository.getDescriptorFor(pInstance.getClass());
// force loading of references
final boolean forced = true;
- retrieveReferences(pInstance, cld, forced);
- retrieveCollections(pInstance, cld, forced);
+ retrieveReferences(pInstance, cld, forced, null);
+ retrieveCollections(pInstance, cld, forced, null);
+ }
+
+ private void addRetrievalTask(HashMap retrievalTasks, Object obj, ObjectReferenceDescriptor rds)
+ {
+ Map identityMap = (Map) retrievalTasks.get(rds);
+
+ if (identityMap == null)
+ {
+ identityMap = IdentityMapFactory.getIdentityMap();
+ retrievalTasks.put(rds, identityMap);
+ }
+ identityMap.put(obj, obj);
}
/**
@@ -1007,14 +1024,14 @@
CollectionDescriptor cod = cld.getCollectionDescriptorByName(pAttributeName);
if (cod != null)
{
- retrieveCollection(pInstance, cld, cod, true);
+ retrieveCollection(pInstance, cld, cod, true, null);
}
else
{
ObjectReferenceDescriptor ord = cld.getObjectReferenceDescriptorByName(pAttributeName);
if (ord != null)
{
- retrieveReference(pInstance, cld, ord, true);
+ retrieveReference(pInstance, cld, ord, true, null);
}
else
{
@@ -1030,15 +1047,16 @@
* @param newObj the instance to be loaded or refreshed
* @param cld the ClassDescriptor of the instance
* @param forced if set to true loading is forced even if cld differs.
+ * @param retrievalTasks tasks for reference or collection retrieval grouped by descriptor
*/
- public void retrieveReferences(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException
+ public void retrieveReferences(Object newObj, ClassDescriptor cld, boolean forced, HashMap retrievalTasks) throws PersistenceBrokerException
{
Iterator i = cld.getObjectReferenceDescriptors().iterator();
ObjectReferenceDescriptor rds = null;
while (i.hasNext())
{
rds = (ObjectReferenceDescriptor) i.next();
- retrieveReference(newObj, cld, rds, forced);
+ retrieveReference(newObj, cld, rds, forced, retrievalTasks);
}
}
@@ -1051,16 +1069,25 @@
* @param cld - the ClassDescriptor describring obj
* @param rds - the ObjectReferenceDescriptor of the reference attribute to be loaded
* @param forced - if set to true, the reference is loaded even if the rds differs.
+ * @param retrievalTasks tasks for reference or collection retrieval grouped by descriptor
*/
- private void retrieveReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forced)
+ private void retrieveReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forced, HashMap retrievalTasks)
{
PersistentField refField;
Object refObj;
if (forced || rds.getCascadeRetrieve())
{
- refObj = getReferencedObject(obj, rds, cld);
- refField = rds.getPersistentField();
- refField.set(obj, refObj);
+ if ((retrievalTasks != null) && !rds.isLazy()
+ && (rds.getItemProxyClass() == null))
+ {
+ addRetrievalTask(retrievalTasks, obj, rds);
+ }
+ else
+ {
+ refObj = getReferencedObject(obj, rds, cld);
+ refField = rds.getPersistentField();
+ refField.set(obj, refObj);
+ }
}
}
@@ -1073,44 +1100,54 @@
* @param cld - the ClassDescriptor describing obj
* @param cds - the CollectionDescriptor describing the collection attribute to be loaded
* @param forced - if set to true loading is forced, even if cds differs.
+ * @param retrievalTasks tasks for reference or collection retrieval grouped by descriptor
*
*/
- private void retrieveCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced)
+ private void retrieveCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced, HashMap retrievalTasks)
{
if (forced || cds.getCascadeRetrieve())
{
- // this collection type will be used:
- Class collectionClass = cds.getCollectionClass();
- PersistentField collectionField = cds.getPersistentField();
- Query fkQuery = getFKQuery(obj, cld, cds);
-
- if (collectionClass == null)
- {
- Collection result = getCollectionByQuery(fkQuery, cds.isLazy());
-
- // assign collection to objects attribute
- // if attribute has an array type build an array, else assign collection directly
- if (collectionField.getType().isArray())
+ if ((retrievalTasks != null) && !cds.isLazy() && !cds.isMtoNRelation()
+ && (cds.getItemProxyClass() == null)
+ && (cds.getQueryCustomizer() == null))
+ {
+ addRetrievalTask(retrievalTasks, obj, cds);
+ }
+ else
+ {
+ // this collection type will be used:
+ Class collectionClass = cds.getCollectionClass();
+ PersistentField collectionField = cds.getPersistentField();
+ Query fkQuery = getFKQuery(obj, cld, cds);
+
+ if (collectionClass == null)
{
- int length = result.size();
- Class itemtype = collectionField.getType().getComponentType();
- Object resultArray = Array.newInstance(itemtype, length);
- for (int j = 0; j < length; j++)
+ Collection result = getCollectionByQuery(fkQuery, cds.isLazy());
+
+ // assign collection to objects attribute
+ // if attribute has an array type build an array, else assign collection directly
+ if (collectionField.getType().isArray())
{
- Array.set(resultArray, j, ((Vector) result).get(j));
+ int length = result.size();
+ Class itemtype = collectionField.getType().getComponentType();
+ Object resultArray = Array.newInstance(itemtype, length);
+ for (int j = 0; j < length; j++)
+ {
+ Array.set(resultArray, j, ((Vector) result).get(j));
+ }
+ collectionField.set(obj, resultArray);
+ }
+ else
+ {
+ collectionField.set(obj, result);
}
- collectionField.set(obj, resultArray);
}
else
{
+ ManageableCollection result = getCollectionByQuery(collectionClass, fkQuery, cds.isLazy());
collectionField.set(obj, result);
}
}
- else
- {
- ManageableCollection result = getCollectionByQuery(collectionClass, fkQuery, cds.isLazy());
- collectionField.set(obj, result);
- }
}
}
@@ -1187,16 +1224,17 @@
* @param newObj the instance to be loaded or refreshed
* @param cld the ClassDescriptor of the instance
* @param forced if set to true, loading is forced even if cld differs
+ * @param retrievalTasks tasks for reference or collection retrieval grouped by descriptor
*
*/
- public void retrieveCollections(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException
+ public void retrieveCollections(Object newObj, ClassDescriptor cld, boolean forced, HashMap retrievalTasks) throws PersistenceBrokerException
{
Iterator i = cld.getCollectionDescriptors().iterator();
CollectionDescriptor cds;
while (i.hasNext())
{
cds = (CollectionDescriptor) i.next();
- retrieveCollection(newObj, cld, cds, forced);
+ retrieveCollection(newObj, cld, cds, forced, retrievalTasks);
}
}
@@ -1218,7 +1256,7 @@
cds = (CollectionDescriptor) iter.next();
if (cds.isRefresh())
{
- retrieveCollection(obj, cld, cds, false);
+ retrieveCollection(obj, cld, cds, false, null);
}
}
//
@@ -1230,7 +1268,7 @@
rds = (ObjectReferenceDescriptor) iter.next();
if (rds.isRefresh())
{
- retrieveReference(obj, cld, rds, false);
+ retrieveReference(obj, cld, rds, false, null);
}
}
}
@@ -1325,11 +1363,14 @@
ClassDescriptor cld = descriptorRepository.getDescriptorFor(itemClass);
ManageableCollection result = null;
OJBIterator iter = null;
+ // Maps ReferenceDescriptors to HashSets of owners
+ HashMap retrievalTasks = (autoPrefetch ? new HashMap() : null);
+
try
{
result = (ManageableCollection) collectionClass.newInstance();
// now iterate over all elements and add them to the new collection
- iter = getIteratorFromQuery(query, cld);
+ iter = getIteratorFromQuery(query, cld, retrievalTasks);
/**
* if the query has specified a start at index, and an end at index move to the start at index.
*/
@@ -1387,6 +1428,7 @@
}
}
+ performRetrievalTasks(retrievalTasks);
/**
* Set full size of query to pass back to client.
*
@@ -1453,6 +1495,32 @@
return result;
}
+ private void performRetrievalTasks(HashMap retrievalTasks)
+ {
+ if (retrievalTasks == null)
+ {
+ return;
+ }
+
+ for (Iterator it = retrievalTasks.keySet().iterator(); it.hasNext(); )
+ {
+ ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) it.next();
+ RelationshipPrefetcher prefetcher;
+ Map identityMap = (Map) retrievalTasks.get(ord);
+ Collection owners = identityMap.values();
+
+ if (ord instanceof CollectionDescriptor)
+ {
+ prefetcher = new CollectionPrefetcher(this, ord);
+ }
+ else
+ {
+ prefetcher = new ReferencePrefetcher(this, ord);
+ }
+ prefetcher.prefetchRelationship(owners);
+ }
+ }
+
/**
* retrieve a collection of type collectionClass matching the Query query
*
@@ -1609,9 +1677,9 @@
final boolean unforced = false;
// 2. retrieve non-skalar fields that contain objects retrievable from other tables
- retrieveReferences(newObj, newObjCld, unforced);
+ retrieveReferences(newObj, newObjCld, unforced, null);
// 3. retrieve collection fields from foreign-key related tables:
- retrieveCollections(newObj, newObjCld, unforced);
+ retrieveCollections(newObj, newObjCld, unforced, null);
}
}
@@ -1681,7 +1749,7 @@
{
Class itemClass = query.getSearchClass();
ClassDescriptor cld = descriptorRepository.getDescriptorFor(itemClass);
- return getIteratorFromQuery(query, cld);
+ return getIteratorFromQuery(query, cld, null);
}
/**
@@ -1689,13 +1757,14 @@
*
* @param query
* @param cld the ClassDescriptor
+ * @param retrievalTasks tasks for reference or collection retrieval grouped by descriptor
* @return OJBIterator
*/
- private OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+ private OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld, HashMap retrievalTasks) throws PersistenceBrokerException
{
RsIteratorFactory factory = RsIteratorFactoryImpl.getInstance();
- return getRsIteratorFromQuery(query, cld, factory);
+ return getRsIteratorFromQuery(query, cld, factory, retrievalTasks);
}
/**
@@ -2343,11 +2412,14 @@
* @param query
* @param cld
* @param factory the Factory for the RsIterator
+ * @param retrievalTasks tasks for reference or collection retrieval grouped by descriptor
* @return OJBIterator
*/
- private OJBIterator getRsIteratorFromQuery(Query query, ClassDescriptor cld, RsIteratorFactory factory)
+ private OJBIterator getRsIteratorFromQuery(Query query, ClassDescriptor cld, RsIteratorFactory factory, HashMap retrievalTasks)
throws PersistenceBrokerException
{
+ RsIterator it;
+
if (query instanceof QueryBySQL)
{
if(logger.isDebugEnabled()) logger.debug("Creating SQL-RsIterator for class ["+cld.getClassNameOfObject()+"]");
@@ -2359,7 +2431,9 @@
{
// no extents just use the plain vanilla RsIterator
if(logger.isDebugEnabled()) logger.debug("Creating RsIterator for class ["+cld.getClassNameOfObject()+"]");
- return factory.createRsIterator(query, cld, this);
+ it = factory.createRsIterator(query, cld, this);
+ it.setRetrievalTasks(retrievalTasks);
+ return it;
}
OJBIterator iter = null;
@@ -2373,7 +2447,9 @@
if (!cld.isInterface())
{
if(logger.isDebugEnabled()) logger.debug("Adding RsIterator for class ["+cld.getClassNameOfObject()+"] to ChainingIterator");
- ((ChainingIterator) iter).addIterator(factory.createRsIterator(query, cld, this));
+ it = factory.createRsIterator(query, cld, this);
+ it.setRetrievalTasks(retrievalTasks);
+ ((ChainingIterator) iter).addIterator(it);
}
for (int i = 0; i < extentClasses.size(); i++)
@@ -2392,7 +2468,7 @@
// add the iterator to the chaining iterator.
// BRJ: look for multilevel hierarchies
if(logger.isDebugEnabled()) logger.debug("Adding RsIterator of class ["+ec+"] to ChainingIterator");
- ((ChainingIterator) iter).addIterator(getRsIteratorFromQuery(query, cld, factory));
+ ((ChainingIterator) iter).addIterator(getRsIteratorFromQuery(query, cld, factory, retrievalTasks));
}
return iter;
}
@@ -2409,7 +2485,7 @@
{
RsIteratorFactory factory = ReportRsIteratorFactoryImpl.getInstance();
- return getRsIteratorFromQuery(query, cld, factory);
+ return getRsIteratorFromQuery(query, cld, factory, null);
}
/**
1.6 +109 -94 db-ojb/src/java/org/apache/ojb/broker/util/IdentityHashMap.java
1.1 db-ojb/src/java/org/apache/ojb/broker/util/IdentityMapFactory.java
Index: IdentityMapFactory.java
===================================================================
package org.apache.ojb.broker.util;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: matthew.baird
* Date: Jul 29, 2003
* Time: 9:16:27 AM
* To change this template use Options | File Templates.
*/
public final class IdentityMapFactory
{
private static boolean HAS_JDK_IDENTITY_MAP = true;
private static final String CLASS_NAME = "java.util.IdentityHashMap";
private static Class JDK_IDENTITY_MAP;
static
{
try
{
JDK_IDENTITY_MAP = Thread.currentThread().getContextClassLoader().loadClass(CLASS_NAME);
}
catch (ClassNotFoundException e)
{
HAS_JDK_IDENTITY_MAP = false;
}
}
private IdentityMapFactory() {}
public static Map getIdentityMap()
{
Map retval = null;
if (HAS_JDK_IDENTITY_MAP)
{
try
{
retval = (Map) JDK_IDENTITY_MAP.newInstance();
}
catch (InstantiationException e)
{
HAS_JDK_IDENTITY_MAP = false;
}
catch (IllegalAccessException e)
{
HAS_JDK_IDENTITY_MAP = false;
}
}
if (!HAS_JDK_IDENTITY_MAP)
{
retval = new org.apache.ojb.broker.util.IdentityHashMap();
}
return retval;
}
}
1.13 +1 -1 db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java
Index: MetadataObjectCopyStrategy.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- MetadataObjectCopyStrategy.java 10 Aug 2003 09:53:13 -0000 1.12
+++ MetadataObjectCopyStrategy.java 25 Aug 2003 19:28:27 -0000 1.13
@@ -59,7 +59,7 @@
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
import org.apache.ojb.broker.accesslayer.CollectionProxy;
import org.apache.ojb.broker.util.ConstructorHelper;
-import org.apache.ojb.otm.util.IdentityMapFactory;
+import org.apache.ojb.broker.util.IdentityMapFactory;
import java.lang.reflect.Constructor;
import java.util.Map;
1.12 +1 -1 db-ojb/src/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java
Index: ReflectiveObjectCopyStrategy.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- ReflectiveObjectCopyStrategy.java 10 Aug 2003 09:53:13 -0000 1.11
+++ ReflectiveObjectCopyStrategy.java 25 Aug 2003 19:28:27 -0000 1.12
@@ -54,7 +54,7 @@
* <http://www.apache.org/>.
*/
-import org.apache.ojb.otm.util.IdentityMapFactory;
+import org.apache.ojb.broker.util.IdentityMapFactory;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org