You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2007/05/16 01:17:23 UTC

svn commit: r538377 - /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java

Author: arminw
Date: Tue May 15 16:17:22 2007
New Revision: 538377

URL: http://svn.apache.org/viewvc?view=rev&rev=538377
Log:
add support for new cascade type, support for PersistenceChecker, optimize source (move m:n stuff), remove 'link' methods handled by BrokerHelper too

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java?view=diff&rev=538377&r1=538376&r2=538377
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java Tue May 15 16:17:22 2007
@@ -37,6 +37,7 @@
 import org.apache.ojb.broker.PersistenceBroker;
 import org.apache.ojb.broker.PersistenceBrokerException;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.PersistenceChecker;
 import org.apache.ojb.broker.TransactionAbortedException;
 import org.apache.ojb.broker.TransactionInProgressException;
 import org.apache.ojb.broker.TransactionNotInProgressException;
@@ -150,6 +151,9 @@
     private LobHelper lobHelper;
     private PBKey pbKey;
     private CollectionTypes collectionTypes;
+    private PersistenceChecker persistenceChecker;
+    //private ObjectContextManager contextManager;
+    //private Linker linker;
 
     /**
      * List of objects being stored now, allows to avoid infinite
@@ -236,6 +240,29 @@
         proxyFactory = AbstractProxyFactory.getProxyFactory();
         brokerHelper = new BrokerHelper(this);
         collectionTypes = new CollectionTypes();
+        Class persistenceCheckerClass = serviceConnectionManager().getConnectionDescriptor().getPersistenceChecker();
+        try
+        {
+            persistenceChecker = (PersistenceChecker) ClassHelper.newInstance(
+                    persistenceCheckerClass, PersistenceBrokerInternal.class, this);
+        }
+        catch(Exception e)
+        {
+            throw new PersistenceBrokerException("Can't instantiate PersistenceChecker implementation class "
+                    + persistenceCheckerClass, e);
+        }
+//        Class contextManagerClass = serviceConnectionManager().getConnectionDescriptor().getObjectContextManager();
+//        try
+//        {
+//            contextManager = (ObjectContextManager) ClassHelper.newInstance(
+//                    contextManagerClass, PersistenceBrokerInternal.class, this);
+//        }
+//        catch(Exception e)
+//        {
+//            throw new PersistenceBrokerException("Can't instantiate ObjectContext implementation class "
+//                    + contextManagerClass, e);
+//        }
+//        linker = new Linker(this);
     }
 
     public void configure(Configuration pConfig) throws ConfigurationException
@@ -324,6 +351,16 @@
         return relationshipPrefetcherFactory;
     }
 
+    public PersistenceChecker getPersistenceChecker()
+    {
+        return persistenceChecker;
+    }
+
+    public MtoNBroker getMtoNBroker()
+    {
+        return mtoNBroker;
+    }
+
     public boolean isClosed()
     {
         return this.isClosed;
@@ -404,6 +441,8 @@
         this.sequenceManager = null;
         this.sqlGenerator = null;
         this.statementManager = null;
+//        this.contextManager.close();
+//        this.contextManager = null;
     }
 
     public PBKey getPBKey()
@@ -634,7 +673,7 @@
         // TODO: arminw: this simple check should do the same - verify
         if (oid.isTransient())
         {
-            String msg = "Cannot delete object without valid PK's: " + obj;
+            String msg = "Can't delete transient (already deleted?) object: " + obj;
             logger.error(msg);
             return;
         }
@@ -665,6 +704,16 @@
     /**
      * This method perform the delete of the specified object
      * based on the {@link org.apache.ojb.broker.metadata.ClassDescriptor}.
+     *
+     * @param cld A intern specified {@link ClassDescriptor}, the real class of the object or a
+     * super-class descriptor.
+     * NOTE: Important to set the super-class descriptor when deleting "table-per-subclass"-inheritance objects.
+     * @param obj The object.
+     * @param ignoreReferences With this flag the automatic deletion/unlinking
+     * of references can be suppressed (independent of the used auto-delete setting in metadata),
+     * except {@link org.apache.ojb.broker.metadata.SuperReferenceDescriptor}
+     * these kind of reference (descriptor) will always be performed.
+     * @throws PersistenceBrokerException if some goes wrong - please see the error message for details
      */
     private void performDeletion(final ClassDescriptor cld, final Object obj, final Identity oid, final boolean ignoreReferences) throws PersistenceBrokerException
     {
@@ -749,7 +798,7 @@
                 String lastUsedTable = cld.getFullTableName();
                 if (cld.isExtent())
                 {
-                    Iterator extents = getDescriptorRepository().getAllConcreteSubclassDescriptors(cld).iterator();
+                    Iterator extents = getDescriptorRepository().getSubclassDescriptors(cld).iterator();
 
                     while (extents.hasNext())
                     {
@@ -783,10 +832,10 @@
      * will be deleted if auto-delete is true <b>AND</b>
      * the member field containing the object reference is NOT null.
      *
-     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor} of the object
-     * or of a super class.
-     * @param obj Object which we will delete references for
-     * @param oid The {@link Identity} of the object.
+     * @param cld A intern specified {@link ClassDescriptor}, the real class of the object or a
+     * super-class descriptor.
+     * NOTE: Important to set the super-class descriptor when deleting "table-per-subclass"-inheritance objects.
+     * @param obj The object.
      * @param ignoreReferences With this flag the automatic deletion/unlinking
      * of references can be suppressed (independent of the used auto-delete setting in metadata),
      * except {@link org.apache.ojb.broker.metadata.SuperReferenceDescriptor}
@@ -797,11 +846,10 @@
     {
         List listRds = cld.getObjectReferenceDescriptors();
         // get all members of obj that are references and delete them
-        Iterator i = listRds.iterator();
-        while (i.hasNext())
+        for(int i = 0; i < listRds.size(); i++)
         {
-            ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
-            if ((!ignoreReferences && rds.getCascadingDelete() == ObjectReferenceDescriptor.CASCADE_OBJECT)
+            ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) listRds.get(i);
+            if ((!ignoreReferences && rds.isCascadingDeleteObject())
                     || rds.isSuperReferenceDescriptor())
             {
                 Object referencedObject = rds.getPersistentField().get(obj);
@@ -845,7 +893,7 @@
         while (i.hasNext())
         {
             CollectionDescriptor cds = (CollectionDescriptor) i.next();
-            if(cds.getCascadingDelete() != ObjectReferenceDescriptor.CASCADE_NONE)
+            if(!cds.isCascadingDeleteNone())
             {
                 if(cds.isMtoNRelation())
                 {
@@ -857,7 +905,7 @@
                 NOTE: User has to take care to populate all referenced objects before delete
                 the main object to avoid referential constraint violation
                  */
-                if (cds.getCascadingDelete() == ObjectReferenceDescriptor.CASCADE_OBJECT)
+                if (cds.isCascadingDeleteObject())
                 {
                     Object col = cds.getPersistentField().get(obj);
                     if (col != null)
@@ -874,6 +922,21 @@
     }
 
     /**
+     * Store only transient/new objects, if the object is persistent (is already
+     * stored) it's skipped - no update will be performed.
+     */
+    public void storeOnlyNew(Object obj) throws PersistenceBrokerException
+    {
+        Class clazz = getProxyFactory().getRealClass(obj);
+        ClassDescriptor cld = getClassDescriptor(clazz);
+        Identity oid = serviceIdentity().buildIdentity(cld, obj);
+        if(!getPersistenceChecker().isPersistent(obj, cld, oid))
+        {
+            store(obj, oid, cld, true);
+        }
+    }
+
+    /**
      * Store an Object.
      * @see org.apache.ojb.broker.PersistenceBroker#store(Object)
      */
@@ -885,22 +948,8 @@
 
         ClassDescriptor cld = getClassDescriptor(obj.getClass());
         Identity oid = serviceIdentity().buildIdentity(cld, obj);
-        /*
-        if one of the PK fields was null, we assume the objects
-        was new and needs insert
-        */
-        // boolean insert = serviceBrokerHelper().hasNullPKField(cld, obj);
-        // TODO: arminw: this should do the same - verify
-        boolean insert = oid.isTransient();
-        /*
-        if PK values are set, lookup cache or db to see whether object
-        needs insert or update
-        */
-        if (!insert)
-        {
-            insert = objectCache.lookup(oid) == null
-                && !serviceBrokerHelper().doesExist(cld, oid, obj);
-        }
+        // Check if object needs insert or update
+        boolean insert = !persistenceChecker.isPersistent(obj, cld, oid);
         store(obj, oid, cld, insert);
     }
 
@@ -917,7 +966,7 @@
         {
             // ProxyObjects only have to be updated if their real
             // subjects have been loaded
-            result = getProxyFactory().getRealObjectIfMaterialized(obj);
+            result = proxyFactory.getRealObjectIfMaterialized(obj);
             // null for unmaterialized Proxy
             if (result == null)
             {
@@ -1051,7 +1100,7 @@
             be performed in any case. The "normal" 1:1 references can be ignored when
             flag "ignoreReferences" is set
             */
-            if((!ignoreReferences && rds.getCascadingStore() != ObjectReferenceDescriptor.CASCADE_NONE)
+            if((!ignoreReferences && !rds.isCascadingStoreNone())
                     || rds.isSuperReferenceDescriptor())
             {
                 storeAndLinkOneToOne(false, obj, cld, rds, insert);
@@ -1066,19 +1115,26 @@
      * @param rds {@link ObjectReferenceDescriptor} of the real object
      * @param insert flag for insert operation
      */
-    private void storeAndLinkOneToOne(boolean onlyLink, Object obj, ClassDescriptor cld,
+    public void storeAndLinkOneToOne(boolean onlyLink, Object obj, ClassDescriptor cld,
                                       ObjectReferenceDescriptor rds, boolean insert)
     {
         Object ref = rds.getPersistentField().get(obj);
-        if (!onlyLink && rds.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
+        if (!onlyLink && ref != null)
         {
-            if(rds.isSuperReferenceDescriptor())
+            if(rds.isCascadingStoreObject())
+            {
+                if(rds.isSuperReferenceDescriptor())
+                {
+                    ClassDescriptor superCld = rds.getClassDescriptor().getSuperClassDescriptor();
+                    Identity oid = serviceIdentity().buildIdentity(superCld, ref);
+                    storeToDb(ref, superCld, oid, insert);
+                }
+                store(ref);
+            }
+            else if(rds.isCascadingStoreCreate())
             {
-                ClassDescriptor superCld = rds.getClassDescriptor().getSuperClassDescriptor();
-                Identity oid = serviceIdentity().buildIdentity(superCld, ref);
-                storeToDb(ref, superCld, oid, insert);
+                storeOnlyNew(ref);
             }
-            else store(ref);
         }
         link(obj, cld, rds, ref, insert);
     }
@@ -1105,7 +1161,7 @@
             CollectionDescriptor cod = (CollectionDescriptor) i.next();
 
             // if CASCADE_NONE was set, do nothing with referenced objects
-            if (cod.getCascadingStore() != ObjectReferenceDescriptor.CASCADE_NONE)
+            if (!cod.isCascadingStoreNone())
             {
                 Object referencedObjects = cod.getPersistentField().get(obj);
                 if (cod.isMtoNRelation())
@@ -1117,10 +1173,10 @@
                     storeAndLinkOneToMany(false, obj, cod, referencedObjects, insert);
                 }
 
-                // BRJ: only when auto-update = object (CASCADE_OBJECT)
-                //
-                if ((cod.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
-                        && (referencedObjects instanceof ManageableCollection))
+                // BRJ: only when auto-update is 'object' (CASCADE_OBJECT)
+                // or with CASCADE_CREATE
+                if ((referencedObjects instanceof ManageableCollection)
+                        && (cod.isCascadingStoreObject() || cod.isCascadingStoreCreate()))
                 {
                     ((ManageableCollection) referencedObjects).afterStore(this);
                 }
@@ -1163,38 +1219,24 @@
             */
             Iterator referencedObjectsIterator;
 
-            if(!onlyLink && cod.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
+            boolean cascadingStoreCreate = cod.isCascadingStoreCreate();
+            if(!onlyLink && (cascadingStoreCreate || cod.isCascadingStoreObject()))
             {
                 referencedObjectsIterator = BrokerHelper.getCollectionIterator(referencedObjects);
                 while (referencedObjectsIterator.hasNext())
                 {
-                    store(referencedObjectsIterator.next());
+                    Object refObj = referencedObjectsIterator.next();
+                    if(cascadingStoreCreate)
+                    {
+                        storeOnlyNew(refObj);
+                    }
+                    else
+                    {
+                        store(refObj);
+                    }
                 }
             }
-
-            Collection existingMtoNKeys;
-            if(!insert)
-            {
-                existingMtoNKeys = mtoNBroker.getMtoNImplementor(cod, obj);
-                // we can't reuse iterator
-                referencedObjectsIterator = BrokerHelper.getCollectionIterator(referencedObjects);
-                // remove all entries in indirection table which not be part of referenced objects
-                mtoNBroker.deleteMtoNImplementor(cod, obj, referencedObjectsIterator, existingMtoNKeys);
-            }
-            else
-            {
-                existingMtoNKeys = Collections.EMPTY_LIST;
-            }
-            // we can't reuse iterator
-            referencedObjectsIterator = BrokerHelper.getCollectionIterator(referencedObjects);
-            while (referencedObjectsIterator.hasNext())
-            {
-                Object refObj = referencedObjectsIterator.next();
-                // Now store indirection record
-                // BRJ: this could cause integrity problems because
-                // obj may not be stored depending on auto-update
-                mtoNBroker.storeMtoNImplementor(cod, obj, refObj, existingMtoNKeys);
-            }
+            mtoNBroker.storeMtoN(obj, cod, referencedObjects, insert);
         }
     }
 
@@ -1208,7 +1250,7 @@
      * @param referencedObjects the referenced objects ({@link ManageableCollection} or Collection or Array) or null
      * @param insert flag for insert operation
      */
-    private void storeAndLinkOneToMany(boolean linkOnly, Object obj, CollectionDescriptor cod,
+    public void storeAndLinkOneToMany(boolean linkOnly, Object obj, CollectionDescriptor cod,
                                        Object referencedObjects, boolean insert)
     {
         if(referencedObjects == null)
@@ -1249,10 +1291,17 @@
                     // get the real object before linking
                     refObj = getProxyFactory().getRealObject(refObj);
                     link(refObj, refCld, cod, obj, insert);
-                    // if enabled cascade store and not only link, store the refObj
-                    if(!linkOnly && cod.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
+                    // if enabled cascade store or store on insert, store the referenced objects
+                    if(!linkOnly)
                     {
-                        store(refObj);
+                        if(cod.isCascadingStoreCreate())
+                        {
+                            storeOnlyNew(refObj);
+                        }
+                        else if(cod.isCascadingStoreObject())
+                        {
+                            store(refObj);
+                        }
                     }
                 }
             }
@@ -1355,70 +1404,6 @@
     }
 
     /**
-     * Assign FK value of main object with PK values of the reference object.
-     *
-     * @param obj real object with reference (proxy) object (or real object with set FK values on insert)
-     * @param cld {@link ClassDescriptor} of the real object
-     * @param rds An {@link ObjectReferenceDescriptor} of real object.
-     * @param insert Show if "linking" is done while insert or update.
-     */
-    public void linkOneToOne(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean insert)
-    {
-        storeAndLinkOneToOne(true, obj, cld, rds, true);
-    }
-
-    /**
-     * Assign FK value to all n-side objects referenced by given object.
-     *
-     * @param obj real object with 1:n reference
-     * @param cod {@link CollectionDescriptor} of referenced 1:n objects
-     * @param insert flag signal insert operation, false signals update operation
-     */
-    public void linkOneToMany(Object obj, CollectionDescriptor cod, boolean insert)
-    {
-        Object referencedObjects = cod.getPersistentField().get(obj);
-        storeAndLinkOneToMany(true, obj, cod,referencedObjects, insert);
-    }
-
-    /**
-     * Assign FK values and store entries in indirection table
-     * for all objects referenced by given object.
-     *
-     * @param obj real object with 1:n reference
-     * @param cod {@link CollectionDescriptor} of referenced 1:n objects
-     * @param insert flag signal insert operation, false signals update operation
-     */
-    public void linkMtoN(Object obj, CollectionDescriptor cod, boolean insert)
-    {
-        Object referencedObjects = cod.getPersistentField().get(obj);
-        storeAndLinkMtoN(true, obj, cod, referencedObjects, insert);
-    }
-
-    public void unlinkXtoN(Object obj, CollectionDescriptor col)
-    {
-        if(col.isMtoNRelation())
-        {
-            // if this is a m:n mapped table, remove entries from indirection table
-            mtoNBroker.deleteMtoNImplementor(col, obj);
-        }
-        else
-        {
-            Object collectionObject = col.getPersistentField().get(obj);
-            if (collectionObject != null)
-            {
-                Iterator colIterator = BrokerHelper.getCollectionIterator(collectionObject);
-                ClassDescriptor cld = null;
-                while (colIterator.hasNext())
-                {
-                    Object target = colIterator.next();
-                    if(cld == null) cld = getClassDescriptor(getProxyFactory().getRealClass(target));
-                    unlinkFK(target, cld, col);
-                }
-            }
-        }
-    }
-
-    /**
      * Retrieve all References (also Collection-attributes) of a given instance.
      * Loading is forced, even if the collection- and reference-descriptors differ.
      * @param pInstance the persistent instance to work with
@@ -1623,7 +1608,7 @@
         // we can lookup all tables of the extent classes:
         if (newObj == null && cld.isExtent())
         {
-            Iterator extents = getDescriptorRepository().getAllConcreteSubclassDescriptors(cld).iterator();
+            Iterator extents = getDescriptorRepository().getSubclassDescriptors(cld).iterator();
 
             while (extents.hasNext())
             {
@@ -2239,7 +2224,7 @@
                 iteratorMap.put(cld.getFullTableName() ,wrapWithPagingIteratorIfNeeded(tmp, query));
             }
 
-            Iterator extents = getDescriptorRepository().getAllConcreteSubclassDescriptors(cld).iterator();
+            Iterator extents = getDescriptorRepository().getSubclassDescriptors(cld).iterator();
             while (extents.hasNext())
             {
                 ClassDescriptor extCld = (ClassDescriptor) extents.next();



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