db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r469563 [1/2] - in /db/ojb/trunk/src/java/org/apache/ojb/odmg: ./ oql/
Date Tue, 31 Oct 2006 17:09:21 GMT
Author: arminw
Date: Tue Oct 31 09:09:20 2006
New Revision: 469563

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

Modified:
    db/ojb/trunk/src/java/org/apache/ojb/odmg/DatabaseImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationExt.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/NarrowTransaction.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelope.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/odmg/oql/OQLQueryImpl.java

Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/DatabaseImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/DatabaseImpl.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/DatabaseImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/DatabaseImpl.java Tue Oct 31 09:09:20 2006
@@ -287,9 +287,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());
     }
 
     /**
@@ -316,6 +315,5 @@
         }
         RuntimeObject rt = new RuntimeObject(object, tx);
         tx.deletePersistent(rt);
-//        tx.moveToLastInOrderList(rt.getIdentity());
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationExt.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationExt.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationExt.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationExt.java Tue Oct 31 09:09:20 2006
@@ -29,24 +29,24 @@
  */
 public interface ImplementationExt extends Implementation
 {
-    /**
-     * The used collection type class returned by OQL queries.
-     *
-     * @see org.apache.ojb.odmg.oql.EnhancedOQLQuery#execute()
-     * @see org.odmg.OQLQuery#execute()
-     * @return The collection class type
-     */
-    public Class getOqlCollectionClass();
-
-    /**
-     * Set the used collection type class returned by OQL queries.
-     * <p/>
-     * NOTE: Each specified class must implement interface {@link org.apache.ojb.broker.ManageableCollection}
-     * to work proper with OJB.
-     *
-     * @param oqlCollectionClass The collection class used in OQL queries.
-     */
-    public void setOqlCollectionClass(Class oqlCollectionClass);
+//    /**
+//     * The used collection type class returned by OQL queries.
+//     *
+//     * @see org.apache.ojb.odmg.oql.EnhancedOQLQuery#execute()
+//     * @see org.odmg.OQLQuery#execute()
+//     * @return The collection class type
+//     */
+//    public Class getOqlCollectionClass();
+//
+//    /**
+//     * Set the used collection type class returned by OQL queries.
+//     * <p/>
+//     * NOTE: Each specified class must implement interface {@link org.apache.ojb.broker.ManageableCollection}
+//     * to work proper with OJB.
+//     *
+//     * @param oqlCollectionClass The collection class used in OQL queries.
+//     */
+//    public void setOqlCollectionClass(Class oqlCollectionClass);
 
     /**
      * If the OJB implicit locking feature (see {@link TransactionExt#setImplicitLocking(boolean)}) is
@@ -135,48 +135,43 @@
     public void setOrdering(boolean ordering);
 
     /**
-     * Return OJB's odmg-specific {@link org.apache.ojb.odmg.locking.LockManager}.
+     * If returns <em>true</em> transient objects will be detected in an
+     * optimized and performant way.
+     *
+     * @see #setOptimizedTransientObjectDetection(boolean)
+     * @return The mode setting.
      */
-    public LockManager getLockManager();
+    public boolean isOptimizedTransientObjectDetection();
 
-//    /**
-//     * 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);
+    /**
+     * 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);
 
 
-//    /**
-//     * 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);
+    /**
+     * Return OJB's odmg-specific {@link org.apache.ojb.odmg.locking.LockManager}.
+     */
+    public LockManager getLockManager();
 
 //    /**
 //     * If set <em>true</em> the odmg implementation do it's best to find out the user intension, if set

Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationImpl.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/ImplementationImpl.java Tue Oct 31 09:09:20 2006
@@ -44,10 +44,6 @@
 /**
  * Default implementation of the {@link Implementation} 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 ImplementationImpl implements ImplementationExt
@@ -59,12 +55,12 @@
     private LockManager lockManager;
     private org.apache.ojb.broker.OJB ojb;
 
-    private Class oqlCollectionClass;
     private boolean impliciteWriteLocks;
     private boolean implicitLocking;
     private boolean implicitLockingBackward;
     private boolean ordering;
     private boolean managed = false;
+    private boolean optimizedTransientObjectDetection;
 
     /**
      * Creates a new implementation instance. Please do not use this directly
@@ -365,22 +361,6 @@
     }
 
     /**
-     * @see ImplementationExt#getOqlCollectionClass()
-     */
-    public Class getOqlCollectionClass()
-    {
-        return oqlCollectionClass;
-    }
-
-    /**
-     * @see ImplementationExt#setOqlCollectionClass(Class)
-     */
-    public void setOqlCollectionClass(Class oqlCollectionClass)
-    {
-        this.oqlCollectionClass = oqlCollectionClass;
-    }
-
-    /**
      * @see ImplementationExt#setImpliciteWriteLocks(boolean)
      */
     public void setImpliciteWriteLocks(boolean impliciteWriteLocks)
@@ -406,6 +386,16 @@
         this.ordering = ordering;
     }
 
+    public boolean isOptimizedTransientObjectDetection()
+    {
+        return optimizedTransientObjectDetection;
+    }
+
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection)
+    {
+        this.optimizedTransientObjectDetection = optimizedTransientObjectDetection;
+    }
+
     /**
      * Allow to use method {@link #setImplicitLocking(boolean)} in the same way
      * as before version 1.0.4 - if set 'true', recommended setting is 'false'.
@@ -434,7 +424,7 @@
                 .append("implicitLocking", isImplicitLocking())
                 .append("implicitWriteLocks", isImpliciteWriteLocks())
                 .append("ordering", isOrdering())
-                .append("oqlCollectionClass", getOqlCollectionClass())
+                //.append("oqlCollectionClass", getOqlCollectionClass())
                 .append("txManager", getTxManager())
                 .append("lockManager", getLockManager())
                 .toString();

Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/NarrowTransaction.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/NarrowTransaction.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/NarrowTransaction.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/NarrowTransaction.java Tue Oct 31 09:09:20 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/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelope.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelope.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelope.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelope.java Tue Oct 31 09:09:20 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.ProxyFactory;
 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,20 +100,35 @@
         this.linkEntryList = new ArrayList();
         this.buffer = buffer;
         this.oid = oid;
+        PersistenceBrokerInternal pb = getBroker();
+        myObj = obj;
         // TODO: do we really need to materialize??
-        myObj = getProxyFactory().getRealObject(obj);
+        realObject = pb.getProxyFactory().getRealObject(obj);
         prepareInitialState(isNewObject);
-        beforeImage = buildObjectImage(getBroker(), isNewObject);
+        beforeImage = buildObjectImage(isNewObject);
     }
 
-    private ProxyFactory getProxyFactory()
+    ObjectEnvelope(ObjectEnvelopeTable buffer, Identity oid, ClassDescriptor cld, Object obj, boolean isNewObject)
     {
-        return buffer.getTransaction().getBrokerInternal().getProxyFactory();
+        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??
+        realObject = pb.getProxyFactory().getRealObject(obj);
+        prepareInitialState(isNewObject);
+        beforeImage = buildObjectImage(isNewObject);
     }
 
     public PersistenceBrokerInternal getBroker()
     {
-        return buffer.getTransaction().getBrokerInternal();
+        if(broker == null)
+        {
+            broker = buffer.getTransaction().getBrokerInternal();
+        }
+        return broker;
     }
 
     TransactionImpl getTx()
@@ -125,7 +145,7 @@
     {
         if(beforeImage == null)
         {
-            beforeImage = buildObjectImage(getBroker());
+            beforeImage = buildObjectImage(false);
         }
         return beforeImage;
     }
@@ -134,7 +154,7 @@
     {
         if(currentImage == null)
         {
-            currentImage = buildObjectImage(getBroker(), needsInsert());
+            currentImage = buildObjectImage(needsInsert());
         }
         return currentImage;
     }
@@ -146,6 +166,7 @@
      */
     public void cleanup(boolean reuse, boolean wasInsert)
     {
+        broker = null;
         if(currentImage != null)
         {
             performImageCleanup(currentImage, reuse);
@@ -157,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();
@@ -164,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);
         }
     }
@@ -183,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,
@@ -200,7 +231,7 @@
             {
                 if(beforeImage == null)
                 {
-                    beforeImage = buildObjectImage(getBroker(), wasNewObject);
+                    beforeImage = buildObjectImage(wasNewObject);
                 }
             }
             currentImage = null;
@@ -273,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 getProxyFactory().getRealObject(myObj);
+        if(realObject == null)
+        {
+            realObject = getBroker().getProxyFactory().getRealObject(getObject());
+        }
+        return realObject;
     }
 
     public void refreshObjectIfNeeded(Object obj)
@@ -290,6 +328,7 @@
         if(this.myObj != obj)
         {
             this.myObj = obj;
+            this.realObject = null;
         }
     }
 
@@ -356,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);
@@ -381,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)
@@ -393,9 +424,9 @@
             */
             if(!rds.isSuperReferenceDescriptor())
             {
-                Object referenceObject = rds.getPersistentField().get(myObj);
+                Object referenceObject = rds.getPersistentField().get(getRealObject());
 
-                IndirectionHandler handler = getProxyFactory().getIndirectionHandler(referenceObject);
+                IndirectionHandler handler = getBroker().getProxyFactory().getIndirectionHandler(referenceObject);
                 /*
                 arminw:
                 if object was serialized and anonymous FK are used in the main object, the FK
@@ -405,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);
@@ -426,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);
         }
@@ -524,7 +549,6 @@
     public boolean isDeleted(Identity id)
     {
         ObjectEnvelope envelope = buffer.getByIdentity(id);
-
         return (envelope != null && envelope.needsDelete());
     }
 
@@ -620,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);
             }
         }
@@ -642,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()
@@ -698,7 +724,12 @@
 
     ClassDescriptor getClassDescriptor()
     {
-        return getBroker().getClassDescriptor(getProxyFactory().getRealClass(getObject()));
+        if(cld == null)
+        {
+            PersistenceBrokerInternal broker = getBroker();
+            cld = broker.getClassDescriptor(broker.getProxyFactory().getRealClass(getObject()));
+        }
+        return cld;
     }
 
     void addLinkOneToOne(ObjectReferenceDescriptor ord, boolean unlink)
@@ -735,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);
@@ -770,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/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java Tue Oct 31 09:09:20 2006
@@ -22,7 +22,6 @@
 import org.apache.commons.lang.ArrayUtils;
 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.ProxyFactory;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
@@ -71,7 +70,6 @@
  *      we are done.
  * </ol>
  *
- * @author  Gerhard Grosse
  * @version $Id$
  * @since   Nov 15, 2004
  */
@@ -257,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);
         }
     }

Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java Tue Oct 31 09:09:20 2006
@@ -18,13 +18,15 @@
 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;
 import org.apache.commons.lang.builder.ToStringStyle;
-import org.apache.commons.lang.SystemUtils;
 import org.apache.ojb.broker.Identity;
 import org.apache.ojb.broker.OJBRuntimeException;
 import org.apache.ojb.broker.OptimisticLockException;
@@ -49,6 +51,8 @@
 /**
  * Manages all ObjectEnvelopes included by a transaction.
  * Performs commit, and rollack operations on all included Envelopes.
+ *
+ * @version $Id: $
  */
 class ObjectEnvelopeTable
 {
@@ -61,7 +65,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();
 
@@ -262,10 +266,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
@@ -285,10 +285,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()))
@@ -306,12 +306,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())
             {
@@ -406,23 +406,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);
     }
 
     /**
@@ -431,19 +454,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 oe = getByIdentity(oid);
+        if(oe == null)
+        {
+            oe = register(oid, object, isNew);
+        }
+        return oe;
+    }
+
+    public ObjectEnvelope get(RuntimeObject rtObject)
+    //public ObjectEnvelope registerIfNeeded(Object object, boolean isNew)
     {
-        ObjectEnvelope result = getByIdentity(oid);
-        if(result == null)
+        ObjectEnvelope oe = getByIdentity(rtObject.getIdentity());
+        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(rtObject);
         }
-        return result;
+        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()
     {
@@ -540,29 +579,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 = getTransaction()
-                        .getBrokerInternal().getProxyFactory().getIndirectionHandler(depObj);
+                IndirectionHandler handler = pb.getProxyFactory().getIndirectionHandler(depObj);
                 // if the object is not materialized, nothing has changed
                 if(handler == null || handler.alreadyMaterialized())
                 {
@@ -598,7 +637,7 @@
         for(int i = 0; i < descriptor.size(); i++)
         {
             CollectionDescriptor col = (CollectionDescriptor) descriptor.get(i);
-            Object collOrArray = col.getPersistentField().get(source.getObject());
+            Object collOrArray = col.getPersistentField().get(source.getRealObject());
             CollectionProxy proxy = pb.getProxyFactory().getCollectionProxy(collOrArray);
             /*
             on insert we perform only materialized collection objects. This should be
@@ -640,12 +679,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)
@@ -670,7 +709,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);
@@ -686,7 +725,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);
@@ -710,7 +749,7 @@
         {
             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());
             Iterator it = null;
             if(collOrArray != null)
             {

Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java Tue Oct 31 09:09:20 2006
@@ -25,7 +25,6 @@
  * 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 PersistenceBrokerInternal broker, 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 = broker.getProxyFactory().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 = tx.getBrokerInternal().getProxyFactory().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/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java Tue Oct 31 09:09:20 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/trunk/src/java/org/apache/ojb/odmg/TransactionImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionImpl.java?view=diff&rev=469563&r1=469562&r2=469563
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionImpl.java Tue Oct 31 09:09:20 2006
@@ -58,7 +58,6 @@
  * Implementation of Transaction for {@link org.odmg.Transaction}.
  *
  * @version $Id$
- *
  */
 public class TransactionImpl
         implements Transaction, MaterializationListener, CollectionProxyListener, TransactionExt
@@ -76,6 +75,7 @@
     private boolean impliciteWriteLocks;
     private boolean implicitLocking;
     private boolean ordering;
+    private boolean optimizedTransientObjectDetection;
 
     /**
      * The status of the current transaction, as specified by the
@@ -125,6 +125,7 @@
 
     /**
      * Creates new Transaction
+     *
      * @param implementation The odmg Implementation class
      */
     public TransactionImpl(ImplementationImpl implementation)
@@ -133,6 +134,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();
@@ -171,7 +173,7 @@
 
     private void checkForDB()
     {
-        if (curDB == null || !curDB.isOpen())
+        if(curDB == null || !curDB.isOpen())
         {
             log.error("Transaction without a associated open Database.");
             throw new TransactionAbortedExceptionOJB(
@@ -183,7 +185,8 @@
      * Determine whether the transaction is open or not. A transaction is open if
      * a call has been made to <code>begin</code> , but a subsequent call to
      * either <code>commit</code> or <code>abort</code> has not been made.
-     * @return    True if the transaction is open, otherwise false.
+     *
+     * @return True if the transaction is open, otherwise false.
      */
     public boolean isOpen()
     {
@@ -196,11 +199,11 @@
 
     private void checkOpen()
     {
-        if (!isOpen())
+        if(!isOpen())
         {
             throw new TransactionNotInProgressException(
                     "Transaction was not open, call tx.begin() before perform action, current status is: " +
-                    TxUtil.getStatusString(getStatus()));
+                            TxUtil.getStatusString(getStatus()));
         }
     }
 
@@ -222,15 +225,14 @@
      * no effect if the object's current lock is already at or above that level of
      * lock mode.
      *
-     * @param  obj       object to acquire a lock on.
-     * @param  lockMode  lock mode to acquire. The lock modes
+     * @param obj object to acquire a lock on.
+     * @param lockMode lock mode to acquire. The lock modes
      * are <code>READ</code> , <code>UPGRADE</code> , and <code>WRITE</code> .
-     *
-     * @exception  LockNotGrantedException    Description of Exception
+     * @throws LockNotGrantedException Description of Exception
      */
     public void lock(Object obj, int lockMode) throws LockNotGrantedException
     {
-        if (log.isDebugEnabled()) log.debug("lock object was called on tx " + this + ", object is " + obj.toString());
+        if(log.isDebugEnabled()) log.debug("lock object was called on tx " + this + ", object is " + obj.toString());
         checkOpen();
         RuntimeObject rtObject = new RuntimeObject(obj, this);
         lockAndRegister(rtObject, lockMode, isImplicitLocking());
@@ -275,7 +277,7 @@
             (e.g. the odmg collection implementations use this interface)
             with current pc-configuration and OJB's tx-manager.
             */
-            getImplementation().prepareOJBBaseInstance(rtObject.getObj());
+            getImplementation().prepareOJBBaseInstance(objectToRegister);
             /*
             if the object is a Proxy there are two options:
             1. The proxies real subject has already been materialized:
@@ -300,7 +302,7 @@
                 {
                     throw new OJBRuntimeException("Unexpected error, expect an proxy object as indicated: " + rtObject);
                 }
-                if (handler.alreadyMaterialized())
+                if(handler.alreadyMaterialized())
                 {
                     objectToRegister = handler.getRealSubject();
                 }
@@ -322,43 +324,43 @@
                     // to lock the referenced objects too
                     internalLockRegisterReferences(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, cascade);
                 }
-            try
-            {
-                // perform the lock on the object
-                // we don't need to lock new objects
-                if(!rtObject.isNew())
+                try
                 {
+                    // perform the lock on the object
+                    // we don't need to lock new objects
+                    if(!rtObject.isNew())
+                    {
                         internalSingleLock(rtObject.getCld(), rtObject.getIdentity(), lockMode);
-                }
-                // after we locked the object, register it to detect status and changes while tx
+                    }
+                    // after we locked the object, register it to detect status and changes while tx
                     internalSingleRegister(rtObject, lockMode);
-            }
-            catch (Throwable t)
-            {
-                //log.error("Locking of obj " + rtObject.getIdentity() + " failed", t);
-                // if registering of object fails release lock on object, because later we don't
-                // get a change to do this.
-                    implementation.getLockManager().releaseLock(this, rtObject.getIdentity());
-                if(t instanceof LockNotGrantedException)
-                {
-                    throw (LockNotGrantedException) t;
                 }
-                else
+                catch(Throwable t)
                 {
-                    log.error("Unexpected failure while locking", t);
-                    throw new LockNotGrantedException("Locking failed for "
-                            + rtObject.getIdentity()+ ", nested exception is: [" + t.getClass().getName()
-                            + ": " + t.getMessage() + "]");
+                    //log.error("Locking of obj " + rtObject.getIdentity() + " failed", t);
+                    // if registering of object fails release lock on object, because later we don't
+                    // get a change to do this.
+                    implementation.getLockManager().releaseLock(this, rtObject.getIdentity());
+                    if(t instanceof LockNotGrantedException)
+                    {
+                        throw (LockNotGrantedException) t;
+                    }
+                    else
+                    {
+                        log.error("Unexpected failure while locking", t);
+                        throw new LockNotGrantedException("Locking failed for "
+                                + rtObject.getIdentity() + ", nested exception is: [" + t.getClass().getName()
+                                + ": " + t.getMessage() + "]");
+                    }
                 }
-            }
                 if(cascade)
                 {
                     // perform locks and register 1:n and m:n references
                     // If implicit locking is used, we have to use the materialized main object
                     // to lock the referenced objects too
                     internalLockRegisterCollections(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, cascade);
-        }
-    }
+                }
+            }
         }
         else
         {
@@ -369,12 +371,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());
             }
         }
     }
@@ -383,38 +380,37 @@
      * Only lock the specified object, represented by
      * the {@link RuntimeObject} instance.
      *
-     * @param  cld       The {@link org.apache.ojb.broker.metadata.ClassDescriptor}
+     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor}
      * of the object to acquire a lock on.
-     * @param  oid The {@link org.apache.ojb.broker.Identity} of the object to lock.
-     * @param  lockMode  lock mode to acquire. The lock modes
+     * @param oid The {@link org.apache.ojb.broker.Identity} of the object to lock.
+     * @param lockMode lock mode to acquire. The lock modes
      * are <code>READ</code> , <code>UPGRADE</code> , and <code>WRITE</code>.
-     *
-     * @exception  LockNotGrantedException    Description of Exception
+     * @throws LockNotGrantedException Description of Exception
      */
     void internalSingleLock(final ClassDescriptor cld, final Identity oid, final int lockMode) throws LockNotGrantedException
     {
-        if (cld.isAcceptLocks())
+        if(cld.isAcceptLocks())
         {
             LockManager lm = implementation.getLockManager();
-            if (lockMode == Transaction.READ)
+            if(lockMode == Transaction.READ)
             {
-                if (log.isDebugEnabled()) log.debug("Do READ lock on object: " + oid);
+                if(log.isDebugEnabled()) log.debug("Do READ lock on object: " + oid);
                 if(!lm.readLock(this, oid, cld))
                 {
                     throw new LockNotGrantedException("Can not lock for READ: " + oid);
                 }
             }
-            else if (lockMode == Transaction.WRITE)
+            else if(lockMode == Transaction.WRITE)
             {
-                if (log.isDebugEnabled()) log.debug("Do WRITE lock on object: " + oid);
+                if(log.isDebugEnabled()) log.debug("Do WRITE lock on object: " + oid);
                 if(!lm.writeLock(this, oid, cld))
                 {
                     throw new LockNotGrantedException("Can not lock for WRITE: " + oid);
                 }
             }
-            else if (lockMode == Transaction.UPGRADE)
+            else if(lockMode == Transaction.UPGRADE)
             {
-                if (log.isDebugEnabled()) log.debug("Do UPGRADE lock on object: " + oid);
+                if(log.isDebugEnabled()) log.debug("Do UPGRADE lock on object: " + oid);
                 if(!lm.upgradeLock(this, oid, cld))
                 {
                     throw new LockNotGrantedException("Can not lock for UPGRADE: " + oid);
@@ -423,7 +419,7 @@
         }
         else
         {
-            if (log.isDebugEnabled())
+            if(log.isDebugEnabled())
             {
                 log.debug("Class '" + cld.getClassNameOfObject() + "' doesn't accept locks" +
                         " (accept-locks=false) when implicite locked, so OJB skip this object: " + oid);
@@ -452,9 +448,9 @@
         arminw:
         if broker isn't in PB-tx, start tx
         */
-        if (!getBroker().isInTransaction())
+        if(!getBroker().isInTransaction())
         {
-            if (log.isDebugEnabled()) log.debug("call beginTransaction() on PB instance");
+            if(log.isDebugEnabled()) log.debug("call beginTransaction() on PB instance");
             broker.setManaged(implementation.isManaged());
             broker.beginTransaction();
         }
@@ -516,7 +512,7 @@
             /**
              * MBAIRD: Be nice and close the table to release all refs
              */
-            if (log.isDebugEnabled())
+            if(log.isDebugEnabled())
                 log.debug("Close Transaction and release current PB " + broker + " on tx " + this);
             txStatus = Status.STATUS_NO_TRANSACTION;
             // remove current thread from LocalTxManager
@@ -532,8 +528,8 @@
      */
     protected void refresh()
     {
-        if (log.isDebugEnabled()) log.debug("Refresh this transaction for reuse: " + this);
-            // we reuse ObjectEnvelopeTable instance
+        if(log.isDebugEnabled()) log.debug("Refresh this transaction for reuse: " + this);
+        // we reuse ObjectEnvelopeTable instance
         objectEnvelopeTable.prepareForUse();
         // clear the temporary used named roots map
         // we should do that, because same tx instance
@@ -552,15 +548,15 @@
      */
     public void checkpoint()
     {
-        if (log.isDebugEnabled()) log.debug("Checkpoint was called, commit changes hold locks on tx " + this);
+        if(log.isDebugEnabled()) log.debug("Checkpoint was called, commit changes hold locks on tx " + this);
         try
         {
             checkOpen();
             doWriteObjects(true);
             // do commit on PB
-            if (hasBroker() && broker.isInTransaction()) broker.commitTransaction();
+            if(hasBroker() && broker.isInTransaction()) broker.commitTransaction();
         }
-        catch (Throwable t)
+        catch(Throwable t)
         {
             log.error("Checkpoint call failed, do abort transaction", t);
             txStatus = Status.STATUS_MARKED_ROLLBACK;
@@ -581,7 +577,7 @@
      */
     public void flush()
     {
-        if (log.isDebugEnabled())
+        if(log.isDebugEnabled())
         {
             log.debug("Flush was called - write changes to database, do not commit, hold locks on tx " + this);
         }
@@ -591,7 +587,7 @@
             checkOpen();
             doWriteObjects(true);
         }
-        catch (Throwable t)
+        catch(Throwable t)
         {
             log.error("Calling method 'tx.flush()' failed", t);
             txStatus = Status.STATUS_MARKED_ROLLBACK;
@@ -649,18 +645,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());
@@ -679,7 +671,7 @@
             lockAndRegister(rt, Transaction.WRITE);
             markPersistent(rt);
         }
-        catch (org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException ex)
+        catch(org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException ex)
         {
             log.error("Can't persist object: " + rt.getIdentity(), ex);
             throw new org.odmg.ClassNotPersistenceCapableException(ex.getMessage());
@@ -699,22 +691,21 @@
      * Upgrade the lock on the given object to the given lock mode. Method <code>
      * tryLock</code> is the same as <code>lock</code> except it returns a boolean
      * indicating whether the lock was granted instead of generating an exception.
-     * @param  obj          Description of Parameter
-     * @param  lockMode     Description of Parameter
-     * @return              Description of the Returned Value
-     * </code>, <code>UPGRADE</code> , and <code>WRITE</code> .
+     *
+     * @param obj Description of Parameter
+     * @param lockMode Description of Parameter
      * @return true          if the lock has been acquired, otherwise false.
      */
     public boolean tryLock(Object obj, int lockMode)
     {
-        if (log.isDebugEnabled()) log.debug("Try to lock object was called on tx " + this);
+        if(log.isDebugEnabled()) log.debug("Try to lock object was called on tx " + this);
         checkOpen();
         try
         {
             lock(obj, lockMode);
             return true;
         }
-        catch (LockNotGrantedException ex)
+        catch(LockNotGrantedException ex)
         {
             return false;
         }
@@ -751,11 +742,11 @@
         {
             if(needFullCommit())
             {
-            prepareCommit();
-            checkForCommit();
+                prepareCommit();
+                checkForCommit();
 
-            txStatus = Status.STATUS_COMMITTING;
-            if (log.isDebugEnabled()) log.debug("Commit transaction " + this);
+                txStatus = Status.STATUS_COMMITTING;
+                if(log.isDebugEnabled()) log.debug("Commit transaction " + this);
             }
             // now do real commit on broker
             if(hasBroker() && getBroker().isInTransaction()) getBroker().commitTransaction();
@@ -785,10 +776,10 @@
     protected void checkForCommit()
     {
         // Never commit transaction that has been marked for rollback
-        if (txStatus == Status.STATUS_MARKED_ROLLBACK)
+        if(txStatus == Status.STATUS_MARKED_ROLLBACK)
             throw new TransactionAbortedExceptionOJB("Illegal tx-status: tx is already markedRollback");
         // Don't commit if not prepared
-        if (txStatus != Status.STATUS_PREPARED)
+        if(txStatus != Status.STATUS_PREPARED)
             throw new IllegalStateException("Illegal tx-status: Do prepare commit before commit");
     }
 
@@ -799,17 +790,17 @@
      *
      * @throws TransactionAbortedException if the transaction has been aborted
      * for any reason.
-     * @throws  IllegalStateException Method called if transaction is
-     *  not in the proper state to perform this operation
+     * @throws IllegalStateException Method called if transaction is
+     * not in the proper state to perform this operation
      * @throws TransactionNotInProgressException if the transaction is closed.
      */
     protected void prepareCommit() throws TransactionAbortedException, LockNotGrantedException
     {
-        if (txStatus == Status.STATUS_MARKED_ROLLBACK)
+        if(txStatus == Status.STATUS_MARKED_ROLLBACK)
         {
             throw new TransactionAbortedExceptionOJB("Prepare Transaction: tx already marked for rollback");
         }
-        if (txStatus != Status.STATUS_ACTIVE)
+        if(txStatus != Status.STATUS_ACTIVE)
         {
             throw new IllegalStateException("Prepare Transaction: tx status is not 'active', status is " + TxUtil.getStatusString(txStatus));
         }
@@ -819,7 +810,7 @@
             doWriteObjects(false);
             txStatus = Status.STATUS_PREPARED;
         }
-        catch (RuntimeException e)
+        catch(RuntimeException e)
         {
             log.error("Could not prepare for commit", e);
             txStatus = Status.STATUS_MARKED_ROLLBACK;
@@ -837,7 +828,7 @@
         /*
         do nothing if already rolledback
         */
-        if (txStatus == Status.STATUS_NO_TRANSACTION
+        if(txStatus == Status.STATUS_NO_TRANSACTION
                 || txStatus == Status.STATUS_UNKNOWN
                 || txStatus == Status.STATUS_ROLLEDBACK)
         {
@@ -845,7 +836,7 @@
             return;
         }
         // check status of tx
-        if (txStatus != Status.STATUS_ACTIVE && txStatus != Status.STATUS_PREPARED &&
+        if(txStatus != Status.STATUS_ACTIVE && txStatus != Status.STATUS_PREPARED &&
                 txStatus != Status.STATUS_MARKED_ROLLBACK)
         {
             throw new IllegalStateException("Illegal state for abort call, state was '" + TxUtil.getStatusString(txStatus) + "'");
@@ -901,7 +892,7 @@
     public synchronized void begin()
     {
         checkForBegin();
-        if (log.isDebugEnabled()) log.debug("Begin transaction was called on tx " + this);
+        if(log.isDebugEnabled()) log.debug("Begin transaction was called on tx " + this);
         refresh();
         // register transaction
         implementation.getTxManager().registerTx(this);
@@ -914,11 +905,11 @@
         /**
          * Is the associated database non-null and open? ODMG 3.0 says it must be.
          */
-        if ((curDB == null) || !curDB.isOpen())
+        if((curDB == null) || !curDB.isOpen())
         {
             throw new DatabaseClosedException("Database is not open. Must have an open DB to begin the Tx.");
         }
-        if (isOpen())
+        if(isOpen())
         {
             log.error("Transaction is already open");
             throw new org.odmg.TransactionInProgressException("Impossible to call begin on already opened tx");
@@ -937,6 +928,7 @@
     /**
      * Get object by identity. First lookup among objects registered in the
      * transaction, then in persistent storage.
+     *
      * @param id The identity
      * @return The object
      * @throws PersistenceBrokerException
@@ -946,7 +938,7 @@
     {
         checkOpen();
         ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(id);
-        if (envelope != null)
+        if(envelope != null)
         {
             return (envelope.needsDelete() ? null : envelope.getObject());
         }
@@ -968,10 +960,10 @@
         ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(rtObject.getIdentity());
         // if we found an envelope, object is already registered --> we do nothing
         // than refreshing the object!
-        if ((envelope == null))
+        if((envelope == null))
         {
             // register object itself
-            envelope = objectEnvelopeTable.get(rtObject.getIdentity(), rtObject.getObj(), rtObject.isNew());
+            envelope = objectEnvelopeTable.register(rtObject);
         }
         else
         {
@@ -1003,18 +995,16 @@
      */
     private void internalLockRegisterReferences(final ClassDescriptor cld, final Object sourceObject, final int lockMode, final boolean cascade) throws LockNotGrantedException
     {
-        if (implicitLocking)
+        if(implicitLocking)
         {
-            Iterator i = cld.getObjectReferenceDescriptors(true).iterator();
-            ProxyFactory proxyFactory = getBrokerInternal().getProxyFactory();
-            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)
+                if(refObj != null)
                 {
-                    boolean isProxy = proxyFactory.isProxy(refObj);
-                    RuntimeObject rt = isProxy ? new RuntimeObject(refObj, this, false) : new RuntimeObject(refObj, this);
+                    RuntimeObject rt = new RuntimeObject(refObj, this);
                     internalLockRegister(rt, lockMode, cascade);
                 }
             }
@@ -1023,22 +1013,22 @@
 
     private void internalLockRegisterCollections(final ClassDescriptor cld, final Object sourceObject, final int lockMode, boolean cascade) throws LockNotGrantedException
     {
-        if (implicitLocking)
+        if(implicitLocking)
         {
-            Iterator i = cld.getCollectionDescriptors(true).iterator();
             ProxyFactory proxyFactory = getBrokerInternal().getProxyFactory();
-            while (i.hasNext())
+            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)
+                if(col != null)
                 {
                     CollectionProxy proxy = proxyFactory.getCollectionProxy(col);
-                    if (proxy != null)
+                    if(proxy != null)
                     {
-                        if (!proxy.isLoaded())
+                        if(!proxy.isLoaded())
                         {
-                            if (log.isDebugEnabled()) log.debug("adding self as listener to collection proxy");
+                            if(log.isDebugEnabled()) log.debug("adding self as listener to collection proxy");
                             proxy.addListener(this);
                             registeredCollectionProxies.add(proxy);
                             continue;
@@ -1048,14 +1038,14 @@
                     Object item = null;
                     try
                     {
-                        while (colIterator.hasNext())
+                        while(colIterator.hasNext())
                         {
                             item = colIterator.next();
                             RuntimeObject rt = new RuntimeObject(item, this);
-                            if (rt.isProxy())
+                            if(rt.isProxy())
                             {
                                 IndirectionHandler handler = proxyFactory.getIndirectionHandler(item);
-                                if (!handler.alreadyMaterialized())
+                                if(!handler.alreadyMaterialized())
                                 {
                                     registerToIndirectionHandler(handler);
                                     continue;
@@ -1070,7 +1060,7 @@
                             internalLockRegister(rt, lockMode, cascade);
                         }
                     }
-                    catch (LockNotGrantedException e)
+                    catch(LockNotGrantedException e)
                     {
                         String eol = SystemUtils.LINE_SEPARATOR;
                         log.error("Lock not granted, while lock collection references[" +
@@ -1087,10 +1077,11 @@
     }
 
     /**
-     *  this callback is invoked before an Object is materialized
-     *  within an IndirectionHandler.
-     *  @param handler the invoking handler
-     *  @param oid the identity of the object to be materialized
+     * this callback is invoked before an Object is materialized
+     * within an IndirectionHandler.
+     *
+     * @param handler the invoking handler
+     * @param oid the identity of the object to be materialized
      */
     public void beforeMaterialization(IndirectionHandler handler, Identity oid)
     {
@@ -1098,33 +1089,38 @@
     }
 
     /**
-     *  this callback is invoked after an Object is materialized
-     *  within an IndirectionHandler.
-     *  this callback allows to defer registration of objects until
-     *  it's really neccessary.
-     *  @param handler the invoking handler
-     *  @param materializedObject the materialized Object
+     * this callback is invoked after an Object is materialized
+     * within an IndirectionHandler.
+     * this callback allows to defer registration of objects until
+     * it's really neccessary.
+     *
+     * @param handler the invoking handler
+     * @param materializedObject the materialized Object
      */
     public void afterMaterialization(IndirectionHandler handler, Object materializedObject)
     {
         try
         {
             Identity oid = handler.getIdentity();
-            if (log.isDebugEnabled())
-            log.debug("deferred registration: " + oid);
+            if(log.isDebugEnabled())
+                log.debug("deferred registration: " + oid);
             if(!isOpen())
             {
                 log.error("Proxy object materialization outside of a running tx, obj=" + oid);
-                try{throw new Exception("Proxy object materialization outside of a running tx, obj=" + oid);}catch(Exception e)
+                try
                 {
-                e.printStackTrace();
+                    throw new Exception("Proxy object materialization outside of a running tx, obj=" + oid);
+                }
+                catch(Exception e)
+                {
+                    e.printStackTrace();
                 }
             }
             ClassDescriptor cld = getBroker().getClassDescriptor(materializedObject.getClass());
-            RuntimeObject rt = new RuntimeObject(getBrokerInternal(), materializedObject, oid, cld, false, false);
+            RuntimeObject rt = new RuntimeObject(getBrokerInternal(), materializedObject, oid, cld, false);
             lockAndRegister(rt, Transaction.READ, isImplicitLocking());
         }
-        catch (Throwable t)
+        catch(Throwable t)
         {
             log.error("Register materialized object with this tx failed", t);
             throw new LockNotGrantedException(t.getMessage());
@@ -1136,7 +1132,7 @@
     {
         // unregistering manipulates the registeredIndirectionHandlers vector
         // we have to loop through this vector to avoid index proplems.
-        for (int i = registeredIndirectionHandlers.size() - 1; i >= 0; i--)
+        for(int i = registeredIndirectionHandlers.size() - 1; i >= 0; i--)
         {
             unregisterFromIndirectionHandler((IndirectionHandler) registeredIndirectionHandlers.get(i));
         }
@@ -1144,7 +1140,7 @@
 
     protected synchronized void unRegisterFromAllCollectionProxies()
     {
-        for (int i = registeredCollectionProxies.size() - 1; i >= 0; i--)
+        for(int i = registeredCollectionProxies.size() - 1; i >= 0; i--)
         {
             unregisterFromCollectionProxy((CollectionProxy) registeredCollectionProxies.get(i));
         }
@@ -1203,7 +1199,7 @@
         if(!(lm instanceof LockManagerOdmgImpl) && unmaterializedLocks.size() > 0)
         {
             //remove locks for objects which haven't been materialized yet
-            for (Iterator it = unmaterializedLocks.iterator(); it.hasNext();)
+            for(Iterator it = unmaterializedLocks.iterator(); it.hasNext();)
             {
                 RuntimeObject rt = (RuntimeObject) it.next();
                 lm.releaseLock(this, rt.getIdentity());
@@ -1225,7 +1221,7 @@
      */
     public PersistenceBrokerInternal getBrokerInternal()
     {
-        if (broker == null)
+        if(broker == null)
         {
             checkOpen();
             try
@@ -1233,9 +1229,10 @@
                 checkForDB();
                 broker = curDB.getBroker();
             }
-            catch (PBFactoryException e)
+            catch(PBFactoryException e)
             {
-                log.error("Cannot obtain PersistenceBroker from database object", e);
+                log.error("Cannot obtain 'PersistenceBroker' instance from database object: "
+                        + curDB, e);
                 throw new PersistenceBrokerException(e);
             }
         }
@@ -1279,6 +1276,7 @@
     {
         return getBroker().getConfiguration().getOjb().getProxyFactory();
     }
+
     /**
      * @see org.apache.ojb.odmg.TransactionExt#setImplicitLocking(boolean)
      */
@@ -1306,23 +1304,26 @@
      */
     public void afterLoading(CollectionProxy colProxy)
     {
-        if (log.isDebugEnabled()) log.debug("loading a proxied collection a collection: " + colProxy);
+        if(log.isDebugEnabled()) log.debug("loading a proxied collection a collection: " + colProxy);
         PersistenceBrokerInternal broker = getBrokerInternal();
-        for (Iterator iterator = colProxy.iterator(); iterator.hasNext();)
+        for(Iterator iterator = colProxy.iterator(); iterator.hasNext();)
         {
             Object o = iterator.next();
             if(!isOpen())
             {
                 log.error("Collection proxy materialization outside of a running tx, obj=" + o);
-                try{throw new Exception("Collection proxy materialization outside of a running tx, obj=" + o);}
+                try
+                {
+                    throw new Exception("Collection proxy materialization outside of a running tx, obj=" + o);
+                }
                 catch(Exception e)
-                {e.printStackTrace();}
+                {
+                    e.printStackTrace();
+                }
             }
             else
             {
-                Identity oid = broker.serviceIdentity().buildIdentity(o);
-                ClassDescriptor cld = broker.getClassDescriptor(broker.getProxyFactory().getRealClass(o));
-                RuntimeObject rt = new RuntimeObject(broker, o, oid, cld, false, broker.getProxyFactory().isProxy(o));
+                RuntimeObject rt = new RuntimeObject(o, this, false);
                 lockAndRegister(rt, Transaction.READ, isImplicitLocking());
             }
         }
@@ -1332,17 +1333,18 @@
     protected void performTransactionAwareBeforeCommit()
     {
         Enumeration en = objectEnvelopeTable.elements();
-        while (en.hasMoreElements())
+        while(en.hasMoreElements())
         {
             ((ObjectEnvelope) en.nextElement()).beforeCommit();
         }
     }
+
     protected void performTransactionAwareAfterCommit()
     {
         Enumeration en = objectEnvelopeTable.elements();
         try
         {
-            while (en.hasMoreElements())
+            while(en.hasMoreElements())
             {
                 ((ObjectEnvelope) en.nextElement()).afterCommit();
             }
@@ -1353,10 +1355,11 @@
                     " after commit you can't rollback - exception will be skipped.", e);
         }
     }
+
     protected void performTransactionAwareBeforeRollback()
     {
         Enumeration en = objectEnvelopeTable.elements();
-        while (en.hasMoreElements())
+        while(en.hasMoreElements())
         {
             try
             {
@@ -1365,16 +1368,17 @@
             catch(Exception e)
             {
                 log.error("Unexpected error while perform 'TransactionAware#beforeAbort()' listener before rollback of objects" +
-                    " - exception will be skipped to complete rollback.", e);
+                        " - exception will be skipped to complete rollback.", e);
             }
         }
     }
+
     protected void performTransactionAwareAfterRollback()
     {
         Enumeration en = objectEnvelopeTable.elements();
         try
         {
-            while (en.hasMoreElements())
+            while(en.hasMoreElements())
             {
                 ((ObjectEnvelope) en.nextElement()).afterAbort();
             }
@@ -1387,46 +1391,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.serviceSessionCache().lookup(oid, SessionCache.LEVEL_DEEP) == null
-                            && !pb.serviceJdbcAccess().doesExist(cld, oid);
+                    cld = pb.getClassDescriptor(obj.getClass());
                 }
+                // if object was found cache, assume it's old
+                // else make costly check against the DB
+                isNew = pb.serviceSessionCache().lookup(oid, SessionCache.LEVEL_DEEP) == null
+                        && !pb.serviceJdbcAccess().doesExist(cld, oid);
             }
         }
         return isNew;
@@ -1475,7 +1476,7 @@
         {
             for(int i = 0; i < extents.size(); i++)
             {
-                Class extent =  (Class) extents.get(i);
+                Class extent = (Class) extents.get(i);
                 ClassDescriptor tmp = getBroker().getClassDescriptor(extent);
                 setCascadingDelete(tmp, result);
             }
@@ -1493,7 +1494,7 @@
         List collectionRefs = cld.getCollectionDescriptors(true);
         for(int i = 0; i < collectionRefs.size(); i++)
         {
-            Object o =  collectionRefs.get(i);
+            Object o = collectionRefs.get(i);
             runtimeCascadeDeleteMap.put(o, cascade);
         }
     }
@@ -1528,6 +1529,7 @@
 
     /**
      * Return <em>true</em> if the OJB ordering algorithm is enabled.
+     *
      * @see #setOrdering(boolean)
      */
     public boolean isOrdering()
@@ -1550,6 +1552,16 @@
         this.ordering = ordering;
     }
 
+    public boolean isOptimizedTransientObjectDetection()
+    {
+        return optimizedTransientObjectDetection;
+    }
+
+    public void setOptimizedTransientObjectDetection(boolean optimizedTransientObjectDetection)
+    {
+        this.optimizedTransientObjectDetection = optimizedTransientObjectDetection;
+    }
+
     protected void finalize() throws Throwable
     {
         super.finalize();
@@ -1579,6 +1591,7 @@
     //============================================================
     // inner class
     //============================================================
+
     /**
      * This was thrown when something wrong with the cascading delete setting.
      */



---------------------------------------------------------------------
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