db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r469559 - /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/
Date Tue, 31 Oct 2006 17:08:17 GMT
Author: arminw
Date: Tue Oct 31 09:08:15 2006
New Revision: 469559

URL: http://svn.apache.org/viewvc?view=rev&rev=469559
Log:
odmg-api performance improvement

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/DatabaseImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationExt.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NamedRootsMap.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NarrowTransaction.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelope.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/RuntimeObject.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionExt.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionImpl.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/DatabaseImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/DatabaseImpl.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/DatabaseImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/DatabaseImpl.java Tue Oct 31 09:08:15 2006
@@ -34,9 +34,6 @@
 /**
  * Implementation class of the {@link org.odmg.Database} interface.
  * 
- * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
- * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  * @version $Id$
  */
 public class DatabaseImpl implements org.odmg.Database
@@ -291,9 +288,8 @@
         {
             throw new TransactionNotInProgressException("No transaction in progress, cannot persist");
         }
-        RuntimeObject rt = new RuntimeObject(object, getTransaction());
+        RuntimeObject rt = new RuntimeObject(object, getTransaction(), true);
         tx.makePersistent(rt);
-//        tx.moveToLastInOrderList(rt.getIdentity());
     }
 
     /**
@@ -320,6 +316,5 @@
         }
         RuntimeObject rt = new RuntimeObject(object, tx);
         tx.deletePersistent(rt);
-//        tx.moveToLastInOrderList(rt.getIdentity());
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationExt.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationExt.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationExt.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationExt.java Tue Oct 31 09:08:15 2006
@@ -133,44 +133,38 @@
      */
     public void setOrdering(boolean ordering);
 
-//    /**
-//     * Returns whether or not the persistent method calls determine
-//     * the persistent object order on commit.
-//     *
-//     * @see #setNoteUserOrder(boolean)
-//     */
-//    public boolean isNoteUserOrder();
-//
-//    /**
-//     * If <em>true</em> the order of persisting method calls like
-//     * <br/> - {@link org.odmg.Transaction#lock(Object, int)}).
-//     * <br/> - {@link org.odmg.Database#deletePersistent(Object)}).
-//     * <br/> - {@link org.odmg.Database#makePersistent(Object)})
-//     * determine the order of objects before commit.
-//     * <br/>
-//     * If <em>false</em> the ordering was determined by OJB's internal
-//     * method calls and user calls.
-//     * <br/>
-//     * However it's possible to set this value only for the current
-//     * used {@link org.odmg.Transaction} using {@link TransactionExt#setNoteUserOrder(boolean)}
-//     * <p/>
-//     * <strong>NOTE:</strong> If OJB's ordering algorithm (see
-//     * {@link #setOrdering(boolean)}) is enabled, the
-//     * order of objects may change on commit.
-//     *
-//     * @param noteUserOrder If <em>true</em> the order of persisting
-//     * method calls determine the order of objects.
-//     */
-//    public void setNoteUserOrder(boolean noteUserOrder);
+    /**
+     * If returns <em>true</em> transient objects will be detected in an
+     * optimized and performant way.
+     *
+     * @see #setOptimizedTransientObjectDetection(boolean)
+     * @return The mode setting.
+     */
+    public boolean isOptimizedTransientObjectDetection();
 
-
-//    /**
-//     * Get object by OJB's {@link org.apache.ojb.broker.Identity}.
-//     *
-//     * @param id The identity of the object to look for.
-//     * @return The matching object or <em>null</em>.
-//     */
-//    public Object getObjectByIdentity(Identity id);
+    /**
+     * The detection of transient objects could be costly (e.g. if a select of ID in
+     * database is used to check if object already exists) we do: <br/>
+     * a. Check if the object {@link org.apache.ojb.broker.Identity} mark the
+     * specified object as transient. If this is <em>false</em> the object has populated
+     * primary key fields, if <em>true</em> at least one PK field is <em>null</em>
+     * and the object is transient.
+     * <br/>
+     * b. Then we check if the object was already registered in current transaction.
+     * if <em>true</em> we can ask for transient state.
+     * <br/>
+     * c. If the primary key fields are mapped as <em>autoIncrement</em> fields and
+     * <em>optimizedTransientObjectDetection</em> is enabled OJB assume that the object
+     * is persistent.
+     * If the PK fields are not autoIncrement fields or the optimized detection is
+     * disabled a database <em>exists object</em> query is performed to check if the
+     * object is persistent or transient.
+     * <br/>
+     *
+     * @param optimizedTransientObjectDetection If <em>true</em> enable the optimized transient
+     * object detection for the whole application.
+     */
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection);
 
 //    /**
 //     * If set <em>true</em> the odmg implementation do it's best to find out the user intension, if set

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationImpl.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ImplementationImpl.java Tue Oct 31 09:08:15 2006
@@ -68,6 +68,7 @@
     private boolean implicitLockingBackward;
     private boolean ordering;
     private boolean managed = false;
+    private boolean optimizedTransientObjectDetection;
 
     /**
      * private Constructor: use static factory method
@@ -89,6 +90,7 @@
         implicitLocking = conf.getBoolean("ImplicitLocking", true);
         ordering = conf.getBoolean("Ordering", true);
         implicitLockingBackward = conf.getBoolean("ImplicitLockingBackward", false);
+        optimizedTransientObjectDetection = conf.getBoolean("OptimizedTransientObjectDetection", true);
         if(log.isEnabledFor(Logger.INFO))
         {
             log.info("Settings: " + this.toString());
@@ -420,6 +422,16 @@
     public void setOrdering(boolean ordering)
     {
         this.ordering = ordering;
+    }
+
+    public boolean isOptimizedTransientObjectDetection()
+    {
+        return optimizedTransientObjectDetection;
+    }
+
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection)
+    {
+        this.optimizedTransientObjectDetection = optimizedTransientObjectDetection;
     }
 
     /**

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NamedRootsMap.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NamedRootsMap.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NamedRootsMap.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NamedRootsMap.java Tue Oct 31 09:08:15 2006
@@ -24,7 +24,7 @@
 import org.apache.ojb.broker.Identity;
 import org.apache.ojb.broker.PersistenceBroker;
 import org.apache.ojb.broker.PersistenceBrokerException;
-import org.apache.ojb.broker.core.proxy.ProxyHelper;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.util.ObjectModification;
 import org.apache.ojb.broker.util.logging.Logger;
@@ -214,11 +214,11 @@
     public void bind(Object object, String name) throws ObjectNameNotUniqueException
     {
         boolean useIdentity = true;
-        PersistenceBroker broker = tx.getBroker();
+        PersistenceBrokerInternal broker = tx.getBrokerInternal();
         ClassDescriptor cld = null;
         try
         {
-            cld = broker.getClassDescriptor(ProxyHelper.getRealClass(object));
+            cld = broker.getClassDescriptor(broker.getProxyFactory().getRealClass(object));
         }
         catch(PersistenceBrokerException ignore)
         {

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NarrowTransaction.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NarrowTransaction.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NarrowTransaction.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/NarrowTransaction.java Tue Oct 31 09:08:15 2006
@@ -185,6 +185,16 @@
         tx.setOrdering(ordering);
     }
 
+    public boolean isOptimizedTransientObjectDetection()
+    {
+        return tx.isOptimizedTransientObjectDetection();
+    }
+
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection)
+    {
+        tx.setOptimizedTransientObjectDetection(optimizedTransientObjectDetection);
+    }
+
 //    public boolean isNoteUserOrder()
 //    {
 //        return tx.isNoteUserOrder();

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelope.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelope.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelope.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelope.java Tue Oct 31 09:08:15 2006
@@ -15,20 +15,19 @@
  * limitations under the License.
  */
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
 import java.util.List;
-import java.util.ArrayList;
+import java.util.Map;
 
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.OJBRuntimeException;
 import org.apache.ojb.broker.PersistenceBroker;
 import org.apache.ojb.broker.PersistenceBrokerException;
-import org.apache.ojb.broker.OJBRuntimeException;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.core.proxy.IndirectionHandler;
-import org.apache.ojb.broker.core.proxy.ProxyHelper;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
 import org.apache.ojb.broker.metadata.FieldDescriptor;
@@ -37,18 +36,20 @@
 import org.apache.ojb.broker.util.ObjectModification;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
+import org.apache.ojb.odmg.link.LinkEntry;
+import org.apache.ojb.odmg.link.LinkEntryOneToN;
+import org.apache.ojb.odmg.link.LinkEntryOneToOne;
 import org.apache.ojb.odmg.states.ModificationState;
 import org.apache.ojb.odmg.states.StateNewDirty;
 import org.apache.ojb.odmg.states.StateOldClean;
 import org.apache.ojb.odmg.states.StateOldDirty;
-import org.apache.ojb.odmg.link.LinkEntry;
-import org.apache.ojb.odmg.link.LinkEntryOneToOne;
-import org.apache.ojb.odmg.link.LinkEntryOneToN;
+import org.odmg.Transaction;
 
 /**
  * ObjectEnvelope is used during ODMG transactions as a wrapper for a
  * persistent objects declaration
  *
+ * @version $Id: $
  */
 public class ObjectEnvelope implements ObjectModification, Image.ImageListener
 {
@@ -65,16 +66,20 @@
      */
     private ModificationState modificationState = null;
     private Identity oid;
+    private ClassDescriptor cld;
+    private PersistenceBrokerInternal broker;
     private Boolean hasChanged;
     private boolean writeLocked;
     private boolean markedForCascadingInsert;
     private boolean markedForCascadingDelete;
-
     /**
-     * myObj holds the object we are wrapping.
+     * The object to wrap (this can be a proxy object)
      */
     private Object myObj;
-
+    /**
+     * The real object instance
+     */
+    private Object realObject;
     /**
      * beforeImage holds a mapping between field
      * names and values at the start of the transaction.
@@ -95,15 +100,35 @@
         this.linkEntryList = new ArrayList();
         this.buffer = buffer;
         this.oid = oid;
+        PersistenceBrokerInternal pb = getBroker();
+        myObj = obj;
+        // TODO: do we really need to materialize??
+        realObject = pb.getProxyFactory().getRealObject(obj);
+        prepareInitialState(isNewObject);
+        beforeImage = buildObjectImage(isNewObject);
+    }
+
+    ObjectEnvelope(ObjectEnvelopeTable buffer, Identity oid, ClassDescriptor cld, Object obj, boolean isNewObject)
+    {
+        this.linkEntryList = new ArrayList();
+        this.buffer = buffer;
+        this.oid = oid;
+        this.cld = cld;
+        PersistenceBrokerInternal pb = getBroker();
+        myObj = obj;
         // TODO: do we really need to materialize??
-        myObj = ProxyHelper.getRealObject(obj);
+        realObject = pb.getProxyFactory().getRealObject(obj);
         prepareInitialState(isNewObject);
-        beforeImage = buildObjectImage(getBroker(), isNewObject);
+        beforeImage = buildObjectImage(isNewObject);
     }
 
     public PersistenceBrokerInternal getBroker()
     {
-        return buffer.getTransaction().getBrokerInternal();
+        if(broker == null)
+        {
+            broker = buffer.getTransaction().getBrokerInternal();
+        }
+        return broker;
     }
 
     TransactionImpl getTx()
@@ -120,7 +145,7 @@
     {
         if(beforeImage == null)
         {
-            beforeImage = buildObjectImage(getBroker());
+            beforeImage = buildObjectImage(false);
         }
         return beforeImage;
     }
@@ -129,7 +154,7 @@
     {
         if(currentImage == null)
         {
-            currentImage = buildObjectImage(getBroker(), needsInsert());
+            currentImage = buildObjectImage(needsInsert());
         }
         return currentImage;
     }
@@ -141,6 +166,7 @@
      */
     public void cleanup(boolean reuse, boolean wasInsert)
     {
+        broker = null;
         if(currentImage != null)
         {
             performImageCleanup(currentImage, reuse);
@@ -152,6 +178,14 @@
         }
         if(reuse)
         {
+            if(wasInsert)
+            {
+                // if we reuse instance, replace transient identity object with real one
+                Identity oldOid = refreshIdentity();
+                buffer.replaceRegisteredIdentity(getIdentity(), oldOid);
+                // lock the new inserted object
+                buffer.getTransaction().internalSingleLock(getClassDescriptor(), getIdentity(), Transaction.WRITE);
+            }
             refreshObjectImage(wasInsert);
             // on reuse of this object, we have to clear the link list
             if(linkEntryList.size() > 0) linkEntryList.clear();
@@ -159,15 +193,17 @@
         else
         {
             myObj = null;
+            realObject = null;
         }
+        cld = null;
     }
 
     private void performImageCleanup(Map imageMap, boolean reuse)
     {
-        Iterator iterator = imageMap.values().iterator();
+        Iterator iterator = imageMap.entrySet().iterator();
         while(iterator.hasNext())
         {
-            Image base =  (Image) iterator.next();
+            Image base =  (Image) ((Map.Entry) iterator.next()).getValue();
             if(base != null) base.cleanup(reuse);
         }
     }
@@ -178,7 +214,7 @@
         {
             markedForCascadingInsert = false;
             markedForCascadingDelete = false;
-            
+
             // if an image already exists we
             // replace the Identity too, maybe a temporary
             // used PK value was replaced by the real one,
@@ -195,7 +231,7 @@
             {
                 if(beforeImage == null)
                 {
-                    beforeImage = buildObjectImage(getBroker(), wasNewObject);
+                    beforeImage = buildObjectImage(wasNewObject);
                 }
             }
             currentImage = null;
@@ -268,16 +304,23 @@
     }
 
     /**
-     * Returns the managed materialized object.
+     * Returns the object (can be a proxy).
      */
     public Object getObject()
     {
         return myObj;
     }
 
+    /**
+     * Returns the real object (no proxy obj).
+     */
     public Object getRealObject()
     {
-        return ProxyHelper.getRealObject(getObject());
+        if(realObject == null)
+        {
+            realObject = getBroker().getProxyFactory().getRealObject(getObject());
+        }
+        return realObject;
     }
 
     public void refreshObjectIfNeeded(Object obj)
@@ -285,6 +328,7 @@
         if(this.myObj != obj)
         {
             this.myObj = obj;
+            this.realObject = null;
         }
     }
 
@@ -351,18 +395,10 @@
         }
     }
 
-    /**
-     * buildObjectImage() will return the image of the Object.
-     */
-    private Map buildObjectImage(PersistenceBroker broker) throws PersistenceBrokerException
-    {
-        return buildObjectImage(broker, false);
-    }
-
-    private Map buildObjectImage(PersistenceBroker broker, boolean isNew) throws PersistenceBrokerException
+    private Map buildObjectImage(boolean isNew) throws PersistenceBrokerException
     {
         Map imageMap = new HashMap();
-        ClassDescriptor cld = broker.getClassDescriptor(getObject().getClass());
+        ClassDescriptor cld = getClassDescriptor();
         //System.out.println("++++ build image: " + getObject());
         // register 1:1 references in image
         buildImageForSingleReferences(imageMap, cld);
@@ -376,11 +412,11 @@
     private void buildImageForSingleReferences(Map imageMap, ClassDescriptor cld)
     {
         // register all 1:1 references
-        Iterator iter = cld.getObjectReferenceDescriptors(true).iterator();
+        List ords = cld.getObjectReferenceDescriptors(true);
         ObjectReferenceDescriptor rds;
-        while(iter.hasNext())
+        for (int i = 0; i < ords.size(); i++)
         {
-            rds = (ObjectReferenceDescriptor) iter.next();
+            rds = (ObjectReferenceDescriptor) ords.get(i);
             /*
             arminw:
             if a "super-reference" is matched (a 1:1 reference used to represent a super class)
@@ -388,9 +424,9 @@
             */
             if(!rds.isSuperReferenceDescriptor())
             {
-                Object referenceObject = rds.getPersistentField().get(myObj);
+                Object referenceObject = rds.getPersistentField().get(getRealObject());
 
-                IndirectionHandler handler = ProxyHelper.getIndirectionHandler(referenceObject);
+                IndirectionHandler handler = getBroker().getProxyFactory().getIndirectionHandler(referenceObject);
                 /*
                 arminw:
                 if object was serialized and anonymous FK are used in the main object, the FK
@@ -400,7 +436,7 @@
                 if(handler == null && referenceObject != null
                         && BrokerHelper.hasAnonymousKeyReference(rds.getClassDescriptor(), rds))
                 {
-                    getBroker().serviceBrokerHelper().link(myObj, rds, false);
+                    getBroker().serviceBrokerHelper().link(getRealObject(), rds, false);
                 }
                 Image.SingleRef singleRef = new Image.SingleRef(this, rds, referenceObject);
                 imageMap.put(rds, singleRef);
@@ -421,25 +457,19 @@
     private void addFieldImage(Map imageMap, FieldDescriptor fld)
     {
         // register copies of all field values
-        Object value = fld.getPersistentField().get(myObj);
-        // get the real sql type value
-        value = fld.getFieldConversion().javaToSql(value);
-        // make copy of the sql type value
-        value = fld.getJdbcType().getFieldType().copy(value);
-        // buffer in image the field name and the sql type value
-        // wrapped by a helper class
+        Object value = fld.getCopyOfValue(getRealObject());
         imageMap.put(fld.getPersistentField().getName(), new Image.Field(fld.getJdbcType().getFieldType(), value));
     }
 
     private void buildImageForCollectionReferences(Map imageMap, ClassDescriptor cld)
     {
         // register the 1:n and m:n references
-        Iterator collections = cld.getCollectionDescriptors(true).iterator();
+        List cdss = cld.getCollectionDescriptors(true);
         CollectionDescriptor cds;
-        while(collections.hasNext())
+        for(int i=0; i<cdss.size(); i++)
         {
-            cds = (CollectionDescriptor) collections.next();
-            Object collectionOrArray = cds.getPersistentField().get(myObj);
+            cds = (CollectionDescriptor) cdss.get(i);
+            Object collectionOrArray = cds.getPersistentField().get(getRealObject());
             Image.MultipleRef colRef = new Image.MultipleRef(this, cds, collectionOrArray);
             imageMap.put(cds, colRef);
         }
@@ -519,7 +549,6 @@
     public boolean isDeleted(Identity id)
     {
         ObjectEnvelope envelope = buffer.getByIdentity(id);
-
         return (envelope != null && envelope.needsDelete());
     }
 
@@ -615,19 +644,22 @@
         // these cases will be handled by ObjectEnvelopeTable#cascadingDependents()
         // if(getModificationState().needsInsert() || getModificationState().needsDelete()) return;
 
+        Map newImage = null;
         Map oldImage = getBeforeImage();
-        Map newImage = getCurrentImage();
-
-        Iterator iter = newImage.entrySet().iterator();
+        Iterator iter = oldImage.entrySet().iterator();
         while (iter.hasNext())
         {
-            Map.Entry entry = (Map.Entry) iter.next();
-            Object key = entry.getKey();
+            Map.Entry oldEntry = (Map.Entry) iter.next();
+            Object key = oldEntry.getKey();
             // we only interested in references
             if(key instanceof ObjectReferenceDescriptor)
             {
-                Image oldRefImage = (Image) oldImage.get(key);
-                Image newRefImage = (Image) entry.getValue();
+                if(newImage == null)
+                {
+                    newImage = getCurrentImage();
+                }
+                Image oldRefImage = (Image) oldEntry.getValue();
+                Image newRefImage = (Image) newImage.get(key);
                 newRefImage.performReferenceDetection(oldRefImage);
             }
         }
@@ -637,22 +669,21 @@
     {
         if(log.isDebugEnabled()) log.debug("Start UPDATE action for " + getIdentity());
         performLinkEntries();
-        getBroker().store(getObject(), getIdentity(), getClassDescriptor(), false, true);
+        getBroker().store(getRealObject(), getIdentity(), getClassDescriptor(), false, true);
     }
 
     public void doInsert()
     {
         if(log.isDebugEnabled()) log.debug("Start INSERT action for " + getIdentity());
         performLinkEntries();
-        getBroker().store(getObject(), getIdentity(), getClassDescriptor(), true, true);
-        Identity oldOid = refreshIdentity();
-        buffer.replaceRegisteredIdentity(getIdentity(), oldOid);
+        getBroker().store(getRealObject(), getIdentity(), getClassDescriptor(), true, true);
     }
 
     public void doDelete()
     {
         if(log.isDebugEnabled()) log.debug("Start DELETE action for " + getIdentity());
-        getBroker().delete(getObject(), true);
+        // use specified object/proxyObject, because delete can be done without materialization
+        getBroker().delete(getObject(), getIdentity(), getClassDescriptor(), true);
     }
 
     public void doEvictFromCache()
@@ -693,7 +724,12 @@
 
     ClassDescriptor getClassDescriptor()
     {
-        return getBroker().getClassDescriptor(ProxyHelper.getRealClass(getObject()));
+        if(cld == null)
+        {
+            PersistenceBrokerInternal broker = getBroker();
+            cld = broker.getClassDescriptor(broker.getProxyFactory().getRealClass(getObject()));
+        }
+        return cld;
     }
 
     void addLinkOneToOne(ObjectReferenceDescriptor ord, boolean unlink)
@@ -730,7 +766,7 @@
         ObjectEnvelope oe = buffer.getByIdentity(oid);
         if(oe == null)
         {
-            RuntimeObject rt = new RuntimeObject(refObjOrProxy, getTx());
+            RuntimeObject rt = new RuntimeObject(refObjOrProxy, oid, getTx());
             // we don't use cascade locking, because new reference object
             // will be detected by ObjectEnvelopeTable#cascadeMarkedForInsert()
             getTx().lockAndRegister(rt, TransactionExt.READ, false);
@@ -765,8 +801,7 @@
         // if the object isn't registered already, it can be 'new' or already 'persistent'
         if(mod == null)
         {
-            boolean isNew = getTx().isTransient(null, refObjOrProxy, oid);
-            mod = buffer.get(oid, refObjOrProxy, isNew);
+            mod = buffer.get(new RuntimeObject(refObjOrProxy, oid, getTx()));
         }
         // if the object was deleted in an previous action, mark as new
         // to avoid deletion, else mark object as dirty to assign the FK of

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java Tue Oct 31 09:08:15 2006
@@ -22,7 +22,7 @@
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.ojb.broker.Identity;
-import org.apache.ojb.broker.core.proxy.ProxyHelper;
+import org.apache.ojb.broker.core.proxy.ProxyFactory;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
@@ -70,7 +70,6 @@
  *      we are done.
  * </ol>
  *
- * @author  Gerhard Grosse
  * @version $Id$
  * @since   Nov 15, 2004
  */
@@ -256,16 +255,16 @@
     private void addEdgesForVertex(Vertex vertex)
     {
         ClassDescriptor cld = vertex.getEnvelope().getClassDescriptor();
-        Iterator rdsIter = cld.getObjectReferenceDescriptors(true).iterator();
-        while (rdsIter.hasNext())
+        List rdss = cld.getObjectReferenceDescriptors(true);
+        for (int i = 0; i < rdss.size(); i++)
         {
-            ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) rdsIter.next();
+            ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) rdss.get(i);
             addObjectReferenceEdges(vertex, rds);
         }
-        Iterator cdsIter = cld.getCollectionDescriptors(true).iterator();
-        while (cdsIter.hasNext())
+        List cdss = cld.getCollectionDescriptors(true);
+        for (int i = 0; i < cdss.size(); i++)
         {
-            CollectionDescriptor cds = (CollectionDescriptor) cdsIter.next();
+            CollectionDescriptor cds = (CollectionDescriptor) cdss.get(i);
             addCollectionEdges(vertex, cds);
         }
     }
@@ -319,7 +318,8 @@
         ObjectEnvelope envelope = vertex.getEnvelope();
         Object col = cds.getPersistentField().get(envelope.getRealObject());
         Object[] refObjects;
-        if (col == null || (ProxyHelper.isCollectionProxy(col) && !ProxyHelper.getCollectionProxy(col).isLoaded()))
+        ProxyFactory pf = envelope.getBroker().getProxyFactory();
+        if (col == null || (pf.isCollectionProxy(col) && !pf.getCollectionProxy(col).isLoaded()))
         {
             refObjects = EMPTY_OBJECT_ARRAY;
         }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java Tue Oct 31 09:08:15 2006
@@ -18,9 +18,11 @@
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.lang.SystemUtils;
 import org.apache.commons.lang.builder.ToStringBuilder;
@@ -29,11 +31,11 @@
 import org.apache.ojb.broker.OJBRuntimeException;
 import org.apache.ojb.broker.OptimisticLockException;
 import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
 import org.apache.ojb.broker.core.proxy.CollectionProxy;
 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
 import org.apache.ojb.broker.core.proxy.IndirectionHandler;
-import org.apache.ojb.broker.core.proxy.ProxyHelper;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
@@ -52,11 +54,7 @@
  * Manages all ObjectEnvelopes included by a transaction.
  * Performs commit, and rollack operations on all included Envelopes.
  *
- * @author Thomas Mahler
- * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
- *
- *         MBAIRD: added explicit closing and de-referencing to prevent any
- *         GC issues.
+ * @version $Id: $
  */
 public class ObjectEnvelopeTable
 {
@@ -69,7 +67,7 @@
      * as "delete". E.g. if a collection reference C is moved from object A1 to A2,
      * then A1 wants to "delete" C and A2 wants to mark the new C object as "new".
      */
-    private final List newAssociatedIdentites = new ArrayList();
+    private final Set newAssociatedIdentites = new HashSet();
     private final List m2nLinkList = new ArrayList();
     private final List m2nUnlinkList = new ArrayList();
 
@@ -271,10 +269,6 @@
             {
                 insert = mod.needsInsert();
                 mod.getModificationState().commit(mod);
-                if(reuse && insert)
-                {
-                    getTransaction().internalSingleLock(mod.getClassDescriptor(), mod.getIdentity(), Transaction.WRITE);
-                }
             }
             /*
             arminw: important to call this cleanup method for each registered
@@ -294,10 +288,10 @@
      */
     private void checkAllEnvelopes(PersistenceBroker broker)
     {
-        Iterator iter = ((List) objectEnvelopesOrderList.clone()).iterator();
-        while(iter.hasNext())
+        List list = ((List) objectEnvelopesOrderList.clone());
+        for(int i = 0; i < list.size(); i++)
         {
-            ObjectEnvelope mod = (ObjectEnvelope) iter.next();
+            ObjectEnvelope mod = (ObjectEnvelope) list.get(i);
             // transient and NewDelete objects must NOT performed
             ModificationState state = mod.getModificationState();
             if(!state.isTransient() && !(state.isNew() && state.isDelete()))
@@ -315,12 +309,12 @@
     private void upgradeLockIfNeeded()
     {
         // using clone to avoid ConcurentModificationException
-        Iterator iter = ((List) objectEnvelopesOrderList.clone()).iterator();
+        List list = ((List) objectEnvelopesOrderList.clone());
         TransactionImpl tx = getTransaction();
         ObjectEnvelope mod;
-        while(iter.hasNext())
+        for(int i = list.size() - 1; i > -1; i--)
         {
-            mod = (ObjectEnvelope) iter.next();
+            mod = (ObjectEnvelope) list.get(i);
             // no need to lock new objects
             if(mod.getModificationState().isNew())
             {
@@ -415,23 +409,46 @@
         return (ObjectEnvelope) objectEnvelopesMap.get(id);
     }
 
-    /** retrieve an objects ObjectModification state from the hashtable */
-    public boolean contains(Identity oid)
+    public boolean isRegistered(Identity oid)
     {
         return objectEnvelopesMap.containsKey(oid);
     }
 
+    public ObjectEnvelope register(Object object, boolean isNew)
+    {
+        PersistenceBrokerInternal pb = transaction.getBrokerInternal();
+        ClassDescriptor cld = pb.getClassDescriptor(pb.getProxyFactory().getRealClass(object));
+        Identity oid = pb.serviceIdentity().buildIdentity(cld, object);
+        return register(oid, cld, object, isNew);
+    }
+
+    public ObjectEnvelope register(Identity oid, Object object, boolean isNew)
+    {
+        PersistenceBrokerInternal pb = transaction.getBrokerInternal();
+        ClassDescriptor cld = pb.getClassDescriptor(pb.getProxyFactory().getRealClass(object));
+        return register(oid, cld, object, isNew);
+    }
+
+    public ObjectEnvelope register(Identity oid, ClassDescriptor cld, Object object, boolean isNew)
+    {
+        ObjectEnvelope oe = new ObjectEnvelope(this, oid, cld, object, isNew);
+        objectEnvelopesMap.put(oid, oe);
+        objectEnvelopesOrderList.add(oe);
+        return oe;
+    }
+
     /**
      * retrieve an objects ObjectEnvelope state from the hashtable.
      * If no ObjectEnvelope is found, a new one is created and returned.
      *
      * @return the resulting ObjectEnvelope
      */
-    public ObjectEnvelope get(Object pKey, boolean isNew)
+    public ObjectEnvelope get(Object object, boolean isNew)
+    //public ObjectEnvelope registerIfNeeded(Object object, boolean isNew)
     {
-        PersistenceBroker broker = transaction.getBroker();
-        Identity oid = broker.serviceIdentity().buildIdentity(pKey);
-        return get(oid, pKey, isNew);
+        Identity oid = transaction.getBrokerInternal().serviceIdentity().buildIdentity(object);
+        //return registerObjectIfNeeded(oid, object, isNew);
+        return get(oid, object, isNew);
     }
 
     /**
@@ -440,19 +457,35 @@
      *
      * @return the resulting ObjectEnvelope
      */
-    public ObjectEnvelope get(Identity oid, Object pKey, boolean isNew)
+    public ObjectEnvelope get(Identity oid, Object object, boolean isNew)
+    //public ObjectEnvelope registerIfNeeded(Identity oid, Object object, boolean isNew)
     {
-        ObjectEnvelope result = getByIdentity(oid);
-        if(result == null)
+        ObjectEnvelope oe = getByIdentity(oid);
+        if(oe == null)
         {
-            result = new ObjectEnvelope(this, oid, pKey, isNew);
-            objectEnvelopesMap.put(oid, result);
-            objectEnvelopesOrderList.add(result);
-            if(log.isDebugEnabled()) log.debug("Register: " + result);
+            oe = register(oid, object, isNew);
         }
-        return result;
+        return oe;
     }
 
+    public ObjectEnvelope get(RuntimeObject rtObject)
+    //public ObjectEnvelope registerIfNeeded(Object object, boolean isNew)
+    {
+        ObjectEnvelope oe = getByIdentity(rtObject.getIdentity());
+        if(oe == null)
+        {
+            oe = register(rtObject);
+        }
+        return oe;
+    }
+
+    public ObjectEnvelope register(RuntimeObject rtObject)
+    {
+        return register(rtObject.getIdentity(), rtObject.getCld(), rtObject.getObj(), rtObject.isNew());
+    }
+
+
+
     /** Returns a String representation of this object */
     public String toString()
     {
@@ -549,28 +582,29 @@
         if(mod.isMarkedForCascadingInsert()) return;
         mod.markForCascadingInsert();
 
-        ClassDescriptor cld = getTransaction().getBroker().getClassDescriptor(mod.getObject().getClass());
+        ClassDescriptor cld = mod.getClassDescriptor();
 
         List refs = cld.getObjectReferenceDescriptors(true);
-        cascadeInsertSingleReferences(mod, refs);
+        if(refs.size() > 0) cascadeInsertSingleReferences(mod, refs);
 
         List colls = cld.getCollectionDescriptors(true);
-        cascadeInsertCollectionReferences(mod, colls);
+        if(colls.size() > 0) cascadeInsertCollectionReferences(mod, colls);
     }
 
     private void cascadeInsertSingleReferences(ObjectEnvelope source, List descriptor)
     {
+        PersistenceBrokerInternal pb = getTransaction().getBrokerInternal();
         for(int i = 0; i < descriptor.size(); i++)
         {
             ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) descriptor.get(i);
-            Object depObj = ord.getPersistentField().get(source.getObject());
+            Object depObj = ord.getPersistentField().get(source.getRealObject());
 
             if(depObj != null)
             {
                 // in any case we have to link the source object when the object needs insert
                 source.addLinkOneToOne(ord, false);
 
-                IndirectionHandler handler = ProxyHelper.getIndirectionHandler(depObj);
+                IndirectionHandler handler = pb.getProxyFactory().getIndirectionHandler(depObj);
                 // if the object is not materialized, nothing has changed
                 if(handler == null || handler.alreadyMaterialized())
                 {
@@ -602,12 +636,12 @@
 
     private void cascadeInsertCollectionReferences(ObjectEnvelope source, List descriptor)
     {
-        // PersistenceBroker pb = getTransaction().getBroker();
+        PersistenceBrokerInternal pb = getTransaction().getBrokerInternal();
         for(int i = 0; i < descriptor.size(); i++)
         {
             CollectionDescriptor col = (CollectionDescriptor) descriptor.get(i);
-            Object collOrArray = col.getPersistentField().get(source.getObject());
-            CollectionProxy proxy = ProxyHelper.getCollectionProxy(collOrArray);
+            Object collOrArray = col.getPersistentField().get(source.getRealObject());
+            CollectionProxy proxy = pb.getProxyFactory().getCollectionProxy(collOrArray);
             /*
             on insert we perform only materialized collection objects. This should be
             sufficient, because in method #cascadingDependents() we make sure that on
@@ -638,7 +672,7 @@
                             object when the main object needs insert, because we have to assign the FK values
                             to the main object
                             */
-                            colObj = ProxyHelper.getRealObject(colObj);
+                            colObj = pb.getProxyFactory().getRealObject(colObj);
                             ObjectEnvelope oe = getByIdentity(oid);
                             if(oe == null)
                             {
@@ -648,12 +682,12 @@
                             if(col.isMtoNRelation())
                             {
                                 // the main objects needs insert, thus add new m:n link
-                                addM2NLinkEntry(col, source.getObject(), colObj);
+                                addM2NLinkEntry(col, source.getRealObject(), colObj);
                             }
                             else
                             {
                                 // we mark collection reference for linking
-                                oe.addLinkOneToN(col, source.getObject(), false);
+                                oe.addLinkOneToN(col, source.getRealObject(), false);
                                 /*
                                 arminw: The referenced object could be already persisted, so we have
                                 to dirty it to guarantee the setting of the FK (linking)
@@ -678,7 +712,7 @@
         if(mod.isMarkedForCascadingDelete()) return;
         mod.markForCascadingDelete();
 
-        ClassDescriptor cld = getTransaction().getBroker().getClassDescriptor(mod.getObject().getClass());
+        ClassDescriptor cld = mod.getClassDescriptor();
 
         List refs = cld.getObjectReferenceDescriptors(true);
         cascadeDeleteSingleReferences(mod, refs);
@@ -694,7 +728,7 @@
             ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) descriptor.get(i);
             if(getTransaction().cascadeDeleteFor(ord))
             {
-                Object depObj = ord.getPersistentField().get(source.getObject());
+                Object depObj = ord.getPersistentField().get(source.getRealObject());
                 if(depObj != null)
                 {
                     Identity oid = getTransaction().getBroker().serviceIdentity().buildIdentity(depObj);
@@ -713,14 +747,14 @@
 
     private void cascadeDeleteCollectionReferences(ObjectEnvelope source, List descriptor)
     {
-        PersistenceBroker pb = getTransaction().getBroker();
+        PersistenceBrokerInternal pb = getTransaction().getBrokerInternal();
         for(int i = 0; i < descriptor.size(); i++)
         {
             CollectionDescriptor col = (CollectionDescriptor) descriptor.get(i);
             boolean cascadeDelete = getTransaction().cascadeDeleteFor(col);
-            Object collOrArray = col.getPersistentField().get(source.getObject());
+            Object collOrArray = col.getPersistentField().get(source.getRealObject());
             // TODO: remove cast
-            CollectionProxyDefaultImpl proxy = (CollectionProxyDefaultImpl) ProxyHelper.getCollectionProxy(collOrArray);
+            CollectionProxyDefaultImpl proxy = (CollectionProxyDefaultImpl) pb.getProxyFactory().getCollectionProxy(collOrArray);
             // on delete we have to materialize dependent objects
             if(proxy != null)
             {
@@ -731,7 +765,7 @@
                 Iterator it = BrokerHelper.getCollectionIterator(collOrArray);
                 while(it.hasNext())
                 {
-                    Object colObj = ProxyHelper.getRealObject(it.next());
+                    Object colObj = pb.getProxyFactory().getRealObject(it.next());
                     Identity oid = pb.serviceIdentity().buildIdentity(colObj);
                     ObjectEnvelope colMod = get(oid, colObj, false);
                     if(cascadeDelete)

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/RuntimeObject.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/RuntimeObject.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/RuntimeObject.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/RuntimeObject.java Tue Oct 31 09:08:15 2006
@@ -15,17 +15,16 @@
  * limitations under the License.
  */
 
+import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.core.proxy.IndirectionHandler;
-import org.apache.ojb.broker.core.proxy.ProxyHelper;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
-import org.apache.commons.lang.builder.ToStringBuilder;
 
 /**
  * Helper object encapsulates common used object properties/states, help to reduce
  * needless metadata calls.
  *
- * @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
  * @version $Id$
  */
 public final class RuntimeObject
@@ -41,7 +40,16 @@
     {
         this.tx = tx;
         this.obj = obj;
-        initCld(tx);
+        init(tx);
+        doIsNewObjectCheck(tx);
+    }
+
+    public RuntimeObject(final Object obj, final Identity oid, final TransactionImpl tx)
+    {
+        this.tx = tx;
+        this.obj = obj;
+        this.identity = oid;
+        init(tx);
         doIsNewObjectCheck(tx);
     }
 
@@ -50,7 +58,7 @@
         this.tx = tx;
         this.obj = obj;
         this.isNew = isNew ? Boolean.TRUE : Boolean.FALSE;
-        initCld(tx);
+        init(tx);
     }
 
     public RuntimeObject(final Object obj, final Identity identity, final TransactionImpl tx, final boolean isNew)
@@ -59,20 +67,18 @@
         this.obj = obj;
         this.identity = identity;
         this.isNew = isNew ? Boolean.TRUE : Boolean.FALSE;
-        initCld(tx);
+        init(tx);
     }
 
-    public RuntimeObject(final Object obj, final Identity oid, final ClassDescriptor cld, final boolean isNew, final boolean isProxy)
+    public RuntimeObject(final PersistenceBrokerInternal broker, final Object obj, final Identity oid,
+                         final ClassDescriptor cld, final boolean isNew)
     {
         this.tx = null;
         this.obj = obj;
         this.identity = oid;
         this.isNew = isNew ? Boolean.TRUE : Boolean.FALSE;
         this.cld = cld;
-        if(isProxy)
-        {
-            this.handler = ProxyHelper.getIndirectionHandler(obj);
-        }
+        this.handler = broker.getProxyFactory().getIndirectionHandler(obj);
     }
 
     /*
@@ -80,9 +86,10 @@
     best performance, thus create Identity object only if needed
     and do 'is new object' check only if needed.
     */
-    private void initCld(final TransactionImpl tx)
+    private void init(final TransactionImpl tx)
     {
-        final IndirectionHandler handler = ProxyHelper.getIndirectionHandler(obj);
+        final PersistenceBrokerInternal pb = tx.getBrokerInternal();
+        final IndirectionHandler handler = pb.getProxyFactory().getIndirectionHandler(obj);
         if(handler != null)
         {
             this.handler = handler;
@@ -90,22 +97,22 @@
             identity = handler.getIdentity();
             if(handler.alreadyMaterialized())
             {
-                cld = tx.getBroker().getClassDescriptor(handler.getRealSubject().getClass());
+                cld = pb.getClassDescriptor(handler.getRealSubject().getClass());
             }
             else
             {
-                cld = tx.getBroker().getClassDescriptor(identity.getObjectsRealClass());
+                cld = pb.getClassDescriptor(identity.getObjectsRealClass());
             }
         }
         else
         {
-            cld = tx.getBroker().getClassDescriptor(obj.getClass());
+            cld = pb.getClassDescriptor(obj.getClass());
         }
     }
 
     void doIsNewObjectCheck(final TransactionImpl tx)
     {
-        boolean isNew = tx.isTransient(cld, obj, null);
+        boolean isNew = !isProxy() && tx.isTransient(cld, obj, getIdentity());
         this.isNew = isNew ? Boolean.TRUE : Boolean.FALSE;
     }
 

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionExt.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionExt.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionExt.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionExt.java Tue Oct 31 09:08:15 2006
@@ -126,36 +126,38 @@
      */
     public void setOrdering(boolean ordering);
 
-//    /**
-//     * Returns whether or not the persistent method calls determine
-//     * the persistent object order on commit.
-//     *
-//     * @see #setNoteUserOrder(boolean)
-//     */
-//    public boolean isNoteUserOrder();
-//
-//    /**
-//     * If <em>true</em> the order of persisting method calls like
-//     * <br/> - {@link org.odmg.Transaction#lock(Object, int)}).
-//     * <br/> - {@link org.odmg.Database#deletePersistent(Object)}).
-//     * <br/> - {@link org.odmg.Database#makePersistent(Object)})
-//     * determine the order of objects before commit.
-//     * <br/>
-//     * If <em>false</em> the ordering was determined by OJB's internal
-//     * method calls and user calls.
-//     * <br/>
-//     * However it's possible to set this value as a global property
-//     * for all transactions using {@link ImplementationExt#setNoteUserOrder(boolean)}.
-//     * <p/>
-//     * <strong>NOTE:</strong> If OJB's ordering algorithm (see
-//     * {@link #setOrdering(boolean)}) is enabled, the
-//     * order of objects may change on commit.
-//     *
-//     * @param noteUserOrder If <em>true</em> the order of persisting
-//     * method calls determine the order of objects.
-//     * @see ImplementationExt#setNoteUserOrder(boolean)
-//     */
-//    public void setNoteUserOrder(boolean noteUserOrder);
+    /**
+     * If returns <em>true</em> transient objects will be detected in an
+     * optimized and performant way.
+     *
+     * @see #setOptimizedTransientObjectDetection(boolean)
+     * @return The mode setting.
+     */
+    public boolean isOptimizedTransientObjectDetection();
+
+    /**
+     * The detection of transient objects could be costly (e.g. if a select of ID in
+     * database is used to check if object already exists) we do: <br/>
+     * a. Check if the object {@link org.apache.ojb.broker.Identity} mark the
+     * specified object as transient. If this is <em>false</em> the object has populated
+     * primary key fields, if <em>true</em> at least one PK field is <em>null</em>
+     * and the object is transient.
+     * <br/>
+     * b. Then we check if the object was already registered in current transaction.
+     * if <em>true</em> we can ask for transient state.
+     * <br/>
+     * c. If the primary key fields are defined/mapped as <em>autoIncrement</em> fields and
+     * <em>optimizedTransientObjectDetection</em> is enabled OJB assume that the object
+     * is persistent.
+     * If the PK fields are not autoIncrement fields or the optimized detection is
+     * disabled a database <em>exists object</em> query is performed to check if the
+     * object is persistent or transient.
+     * <br/>
+     *
+     * @param optimizedTransientObjectDetection If <em>true</em> enable the optimized transient
+     * object detection for this transaction.
+     */
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection);
 
     /**
      * Checks if the object with the given {@link org.apache.ojb.broker.Identity}

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionImpl.java?view=diff&rev=469559&r1=469558&r2=469559
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/odmg/TransactionImpl.java Tue Oct 31 09:08:15 2006
@@ -38,7 +38,7 @@
 import org.apache.ojb.broker.core.proxy.CollectionProxyListener;
 import org.apache.ojb.broker.core.proxy.IndirectionHandler;
 import org.apache.ojb.broker.core.proxy.MaterializationListener;
-import org.apache.ojb.broker.core.proxy.ProxyHelper;
+import org.apache.ojb.broker.core.proxy.ProxyFactory;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
@@ -80,6 +80,7 @@
     private boolean impliciteWriteLocks;
     private boolean implicitLocking;
     private boolean ordering;
+    private boolean optimizedTransientObjectDetection;
 
     /**
      * The status of the current transaction, as specified by the
@@ -137,6 +138,7 @@
         this.impliciteWriteLocks = implementation.isImpliciteWriteLocks();
         this.implicitLocking = implementation.isImplicitLocking();
         this.ordering = implementation.isOrdering();
+        this.optimizedTransientObjectDetection = implementation.isOptimizedTransientObjectDetection();
         // assign a uniqe id to this tx
         txGUID = guid.next();
         curDB = implementation.getCurrentDatabase();
@@ -367,12 +369,7 @@
             */
             if(mod != null)
             {
-                // only use real objects, no proxy instances
-                Object realObj = rtObject.getObjMaterialized();
-                if(realObj != null)
-                {
-                    mod.refreshObjectIfNeeded(realObj);
-                }
+                mod.refreshObjectIfNeeded(rtObject.getObj());
             }
         }
     }
@@ -647,18 +644,14 @@
 
     void markDirty(RuntimeObject rt)
     {
-        ObjectEnvelope otw = objectEnvelopeTable.get(rt.getIdentity(), rt.getObj(), rt.isNew());
+        ObjectEnvelope otw = objectEnvelopeTable.get(rt);
         otw.refreshObjectIfNeeded(rt.getObj());
         otw.setModificationState(otw.getModificationState().markDirty());
     }
 
     void markPersistent(RuntimeObject rtObj)
     {
-        ObjectEnvelope oe = objectEnvelopeTable.getByIdentity(rtObj.getIdentity());
-        if(oe == null)
-        {
-            oe = objectEnvelopeTable.get(rtObj.getIdentity(), rtObj.getObj(), rtObj.isNew());
-        }
+        ObjectEnvelope oe = objectEnvelopeTable.get(rtObj);
         if(oe.needsDelete())
         {
             oe.setModificationState(oe.getModificationState().markNew());
@@ -969,7 +962,7 @@
         if ((envelope == null))
         {
             // register object itself
-            envelope = objectEnvelopeTable.get(rtObject.getIdentity(), rtObject.getObj(), rtObject.isNew());
+            envelope = objectEnvelopeTable.register(rtObject);
         }
         else
         {
@@ -1003,15 +996,14 @@
     {
         if (implicitLocking)
         {
-            Iterator i = cld.getObjectReferenceDescriptors(true).iterator();
-            while (i.hasNext())
+            List ords = cld.getObjectReferenceDescriptors(true);
+            for (int i = 0; i < ords.size(); i++)
             {
-                ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
+                ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) ords.get(i);
                 Object refObj = rds.getPersistentField().get(sourceObject);
                 if (refObj != null)
                 {
-                    boolean isProxy = ProxyHelper.isProxy(refObj);
-                    RuntimeObject rt = isProxy ? new RuntimeObject(refObj, this, false) : new RuntimeObject(refObj, this);
+                    RuntimeObject rt = new RuntimeObject(refObj, this);
                     internalLockRegister(rt, lockMode, cascade);
                 }
             }
@@ -1022,14 +1014,15 @@
     {
         if (implicitLocking)
         {
-            Iterator i = cld.getCollectionDescriptors(true).iterator();
-            while (i.hasNext())
+            ProxyFactory proxyFactory = getBrokerInternal().getProxyFactory();
+            List cdss = cld.getCollectionDescriptors(true);
+            for (int i = 0; i < cdss.size(); i++)
             {
-                CollectionDescriptor cds = (CollectionDescriptor) i.next();
+                CollectionDescriptor cds = (CollectionDescriptor) cdss.get(i);
                 Object col = cds.getPersistentField().get(sourceObject);
                 if (col != null)
                 {
-                    CollectionProxy proxy = ProxyHelper.getCollectionProxy(col);
+                    CollectionProxy proxy = proxyFactory.getCollectionProxy(col);
                     if (proxy != null)
                     {
                         if (!proxy.isLoaded())
@@ -1050,7 +1043,7 @@
                             RuntimeObject rt = new RuntimeObject(item, this);
                             if (rt.isProxy())
                             {
-                                IndirectionHandler handler = ProxyHelper.getIndirectionHandler(item);
+                                IndirectionHandler handler = proxyFactory.getIndirectionHandler(item);
                                 if (!handler.alreadyMaterialized())
                                 {
                                     registerToIndirectionHandler(handler);
@@ -1117,7 +1110,7 @@
                 }
             }
             ClassDescriptor cld = getBroker().getClassDescriptor(materializedObject.getClass());
-            RuntimeObject rt = new RuntimeObject(materializedObject, oid, cld, false, false);
+            RuntimeObject rt = new RuntimeObject(getBrokerInternal(), materializedObject, oid, cld, false);
             lockAndRegister(rt, Transaction.READ, isImplicitLocking());
         }
         catch (Throwable t)
@@ -1320,9 +1313,7 @@
             }
             else
             {
-                Identity oid = getBroker().serviceIdentity().buildIdentity(o);
-                ClassDescriptor cld = getBroker().getClassDescriptor(ProxyHelper.getRealClass(o));
-                RuntimeObject rt = new RuntimeObject(o, oid, cld, false, ProxyHelper.isProxy(o));
+                RuntimeObject rt = new RuntimeObject(o, this, false);
                 lockAndRegister(rt, Transaction.READ, isImplicitLocking());
             }
         }
@@ -1387,46 +1378,43 @@
     }
 
     /**
-     * Detect new objects.
+     * This method help to detect transient/new objects.
+     *
+     * @param obj The non proxy object to detect.
+     * @param oid The {@link org.apache.ojb.broker.Identity} of the object.
+     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor} of
+     * the object or <em>null</em>.
      */
     protected boolean isTransient(ClassDescriptor cld, Object obj, Identity oid)
     {
         // if the Identity is transient we assume a non-persistent object
-        boolean isNew = oid != null && oid.isTransient();
+        boolean isNew = oid.isTransient();
         /*
-        detection of new objects is costly (select of ID in DB to check if object
+        detection of transient objects is costly (select of ID in DB to check if object
         already exists) we do:
-        a. check if the object has nullified PK field
-        b. check if the object is already registered
-        c. lookup from cache and if not found, last option select on DB
+        a. check if the object identity mark the specified object as transient
+        b. lookup from cache
+        c. and if not found, last option select on DB
         */
         if(!isNew)
         {
-            final PersistenceBroker pb = getBroker();
-            if(cld == null)
+            ObjectEnvelope mod = objectEnvelopeTable.getByIdentity(oid);
+            if(mod != null)
             {
-                cld = pb.getClassDescriptor(obj.getClass());
+                // already registered object, use current state
+                isNew = mod.needsInsert();
             }
-            isNew = pb.serviceBrokerHelper().hasNullPKField(cld, obj);
-            if(!isNew)
+            else if(!optimizedTransientObjectDetection || cld.getAutoIncrementFields().length < 1)
             {
-                if(oid == null)
-                {
-                    oid = pb.serviceIdentity().buildIdentity(cld, obj);
-                }
-                final ObjectEnvelope mod = objectEnvelopeTable.getByIdentity(oid);
-                if(mod != null)
+                PersistenceBrokerInternal pb = getBrokerInternal();
+                if(cld == null)
                 {
-                    // already registered object, use current state
-                    isNew = mod.needsInsert();
-                }
-                else
-                {
-                    // if object was found cache, assume it's old
-                    // else make costly check against the DB
-                    isNew = pb.serviceObjectCache().lookup(oid) == null
-                            && !pb.serviceBrokerHelper().doesExist(cld, oid, obj);
+                    cld = pb.getClassDescriptor(obj.getClass());
                 }
+                // if object was found cache, assume it's old
+                // else make costly check against the DB
+                isNew = pb.serviceObjectCache().lookup(oid) == null
+                        && !pb.serviceBrokerHelper().doesExist(cld, oid, obj);
             }
         }
         return isNew;
@@ -1548,6 +1536,16 @@
     public void setOrdering(boolean ordering)
     {
         this.ordering = ordering;
+    }
+
+    public boolean isOptimizedTransientObjectDetection()
+    {
+        return optimizedTransientObjectDetection;
+    }
+
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection)
+    {
+        this.optimizedTransientObjectDetection = optimizedTransientObjectDetection;
     }
 
     protected void finalize() throws Throwable



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message