You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ol...@apache.org on 2003/07/13 16:07:16 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/otm/swizzle CopySwizzling.java NoSwizzling.java Swizzling.java
olegnitz 2003/07/13 07:07:16
Modified: src/java/org/apache/ojb/otm/core ConcreteEditingContext.java
src/java/org/apache/ojb/otm/kit SimpleKit.java
src/java/org/apache/ojb/otm/swizzle CopySwizzling.java
NoSwizzling.java Swizzling.java
Log:
Fixes bugs in handling modifications of relations and collections
Revision Changes Path
1.20 +209 -45 db-ojb/src/java/org/apache/ojb/otm/core/ConcreteEditingContext.java
Index: ConcreteEditingContext.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/core/ConcreteEditingContext.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- ConcreteEditingContext.java 11 Jul 2003 19:30:26 -0000 1.19
+++ ConcreteEditingContext.java 13 Jul 2003 14:07:16 -0000 1.20
@@ -61,6 +61,7 @@
import com.develop.java.lang.reflect.Proxy;
*/
//#endif
+import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
@@ -70,6 +71,8 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Date;
+import java.util.List;
+import java.util.Set;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.ManageableCollection;
@@ -77,10 +80,10 @@
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.VirtualProxy;
-import org.apache.ojb.broker.accesslayer.CollectionProxy;
import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
import org.apache.ojb.broker.accesslayer.IndirectionHandler;
import org.apache.ojb.broker.accesslayer.MaterializationListener;
+import org.apache.ojb.broker.accesslayer.OJBIterator;
import org.apache.ojb.broker.cache.ObjectCache;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.CollectionDescriptor;
@@ -105,7 +108,7 @@
*
*/
public class ConcreteEditingContext
- implements EditingContext, MaterializationListener
+ implements EditingContext, MaterializationListener, ObjectCache
{
// for hasBidirectionalAssociation method
// Maps PBKeys to the sets of classes with/without
@@ -162,10 +165,11 @@
public void insert(Identity oid, Object obj, int lock)
throws LockingException
{
- insertInternal(oid, obj, lock);
+ insertInternal(oid, obj, lock, true);
}
- private ContextEntry insertInternal(Identity oid, Object newObj, int lock)
+ private ContextEntry insertInternal(Identity oid, Object newObj, int lock,
+ boolean mainObject)
throws LockingException
{
ContextEntry entry;
@@ -197,7 +201,7 @@
if (entry == null)
{
lockManager.ensureLock(oid, _tx, lock, _pb);
- Object swizzledObject = swizzlingStrategy.swizzle(newObj, null, _pb);
+ Object swizzledObject = swizzlingStrategy.swizzle(newObj, null, _pb, this);
entry = new ContextEntry(swizzledObject);
if (entry.handler != null)
{
@@ -207,7 +211,7 @@
{
Object origObj;
- if (kit.isInsertVerified())
+ if (!mainObject || kit.isInsertVerified())
{
origObj = _pb.getObjectByIdentity(oid);
}
@@ -257,7 +261,7 @@
oldObj = entry.handler.getRealSubject();
entry.handler = null;
}
- entry.object = swizzlingStrategy.swizzle(newObj, oldObj, _pb);
+ entry.object = swizzlingStrategy.swizzle(newObj, oldObj, _pb, this);
}
}
else
@@ -304,7 +308,7 @@
if (_order.contains(oid)) {
_order.remove(oid);
}
- entry = insertInternal(oid, object, LockType.WRITE_LOCK);
+ entry = insertInternal(oid, object, LockType.WRITE_LOCK, true);
entry.state = entry.state.deletePersistent();
}
@@ -462,12 +466,23 @@
if (!state.needsUpdate() && !state.needsInsert()
&& !state.needsDelete())
{
- Object[] origFields = (Object[]) _checkpointed.get(oid);
+ Object[][] origFields = (Object[][]) _checkpointed.get(oid);
+ Object[][] newFields = getFields(entry.object);
if ((origFields == null)
- || isModified(origFields, getFields(entry.object)))
+ || isModified(origFields[0], newFields[0]))
{
entry.state = state.markDirty();
+ entry.needsCacheSwizzle = true;
+ lockManager.ensureLock(oid, _tx, LockType.WRITE_LOCK, _pb);
+ }
+
+ if ((origFields != null)
+ && isModified(origFields[1], newFields[1]))
+ {
+ // there are modified collections,
+ // so we need to lock the object and to swizzle it to cache
+ entry.needsCacheSwizzle = true;
lockManager.ensureLock(oid, _tx, LockType.WRITE_LOCK, _pb);
}
}
@@ -484,19 +499,20 @@
Identity oid = order[i];
ContextEntry entry = (ContextEntry) _objects.get(oid);
- if (entry.state.needsUpdate())
+ if (entry.needsCacheSwizzle)
{
Object cacheObj = cache.lookup(oid);
entry.object = swizzlingStrategy.getRealTarget(entry.object);
- if ((cacheObj != null)
+ if ((cacheObj != null)
&& !swizzlingStrategy.isSameInstance(entry.object, cacheObj))
{
- entry.object = swizzlingStrategy.swizzle(entry.object, cacheObj, _pb);
+ entry.object = swizzlingStrategy.swizzle(entry.object, cacheObj, _pb, cache);
if (entry.object != cacheObj)
{
cache.cache(oid, entry.object);
}
}
+ entry.needsCacheSwizzle = false;
}
}
@@ -549,7 +565,7 @@
connMan.setBatchMode(saveBatchMode);
}
} catch (Throwable ex) {
- //ex.printStackTrace();
+ ex.printStackTrace();
throw new TransactionAbortedException(ex);
}
}
@@ -566,8 +582,8 @@
{
Identity oid = (Identity) iterator.next();
ContextEntry entry = (ContextEntry) _objects.get(oid);
- Object[] origFields = (Object[]) _original.get(oid);
entry.state = entry.state.rollback();
+ Object[][] origFields = (Object[][]) _original.get(oid);
if (origFields != null)
{
setFields(entry.object, origFields);
@@ -618,7 +634,7 @@
relOid = new Identity(relObj, _pb);
if (!_order.contains(relOid))
{
- insertInternal(relOid, relObj, LockType.READ_LOCK);
+ insertInternal(relOid, relObj, LockType.READ_LOCK, false);
}
}
}
@@ -635,14 +651,6 @@
col = collectionDescriptor.getPersistentField().get(object);
if (col != null)
{
- if (col instanceof CollectionProxy)
- {
- if (!((CollectionProxy) col).isLoaded())
- {
- continue;
- }
- }
-
if (col instanceof ManageableCollection)
{
colIterator = ((ManageableCollection) col).ojbIterator();
@@ -668,9 +676,14 @@
relOid = new Identity(relObj, _pb);
if (!_order.contains(relOid))
{
- insertInternal(relOid, relObj, LockType.READ_LOCK);
+ insertInternal(relOid, relObj, LockType.READ_LOCK, false);
}
}
+
+ if (colIterator instanceof OJBIterator)
+ {
+ ((OJBIterator) colIterator).releaseDbResources();
+ }
}
}
}
@@ -728,44 +741,90 @@
return false;
}
-
- private Object[] getFields(Object obj)
+
+ /**
+ * Two arrays of field values:
+ * 1) The class, simple fields, references
+ * 2) collections
+ */
+ private Object[][] getFields(Object obj)
{
ClassDescriptor mif = _pb.getClassDescriptor(obj.getClass());
FieldDescriptor[] fieldDescs = mif.getFieldDescriptions();
Collection refDescsCol = mif.getObjectReferenceDescriptors();
- ObjectReferenceDescriptor[] refDescs =
- (ObjectReferenceDescriptor[]) refDescsCol.toArray(
- new ObjectReferenceDescriptor[refDescsCol.size()]);
- Object[] fields = new Object[1 + fieldDescs.length + refDescs.length];
+ Collection refDescs = mif.getObjectReferenceDescriptors();
+ Collection colDescs = mif.getCollectionDescriptors();
+ int count = 0;
+ Object[] fields = new Object[1 + fieldDescs.length + refDescs.size()];
+ ArrayList[] collections = new ArrayList[colDescs.size()];
fields[0] = obj.getClass(); // we must notice if the object class changes
+ count++;
for (int i = 0; i < fieldDescs.length; i++)
{
FieldDescriptor fd = fieldDescs[i];
PersistentField f = fd.getPersistentField();
- fields[1 + i] = f.get(obj);
+ fields[count] = f.get(obj);
+ count++;
}
- for (int i = 0; i < refDescs.length; i++)
+ for (Iterator it = refDescs.iterator(); it.hasNext(); count++)
{
- ObjectReferenceDescriptor rds = refDescs[i];
+ ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) it.next();
PersistentField f = rds.getPersistentField();
- fields[1 + fieldDescs.length + i] = f.get(obj);
+ Object relObj = f.get(obj);
+ if (relObj != null)
+ {
+ fields[count] = new Identity(relObj, _pb);
+ }
}
- return fields;
+ count = 0;
+ for (Iterator it = colDescs.iterator(); it.hasNext(); count++)
+ {
+ CollectionDescriptor cds = (CollectionDescriptor) it.next();
+ PersistentField f = cds.getPersistentField();
+ Class type = f.getType();
+ Object col = f.get(obj);
+ if (col != null)
+ {
+ ArrayList list = new ArrayList();
+ Iterator colIterator;
+
+ collections[count] = list;
+ if (Collection.class.isAssignableFrom(type))
+ {
+ colIterator = ((Collection) col).iterator();
+ }
+ else if (type.isArray())
+ {
+ colIterator = new ArrayIterator(col);
+ }
+ else
+ {
+ continue;
+ }
+
+ while (colIterator.hasNext())
+ {
+ list.add(new Identity(colIterator.next(), _pb));
+ }
+ }
+ }
+
+ return new Object[][] {fields, collections};
}
- private void setFields(Object obj, Object[] fields)
+ private void setFields(Object obj, Object[][] fieldsAndCollections)
{
ClassDescriptor mif = _pb.getClassDescriptor(obj.getClass());
FieldDescriptor[] fieldDescs = mif.getFieldDescriptions();
- Collection refDescsCol = mif.getObjectReferenceDescriptors();
- ObjectReferenceDescriptor[] refDescs =
- (ObjectReferenceDescriptor[]) refDescsCol.toArray(
- new ObjectReferenceDescriptor[refDescsCol.size()]);
+ Collection refDescs = mif.getObjectReferenceDescriptors();
+ Collection colDescs = mif.getCollectionDescriptors();
+ Object[] fields = fieldsAndCollections[0];
+ ArrayList[] collections = (ArrayList[]) fieldsAndCollections[1];
+ int count = 0;
if (!fields[0].equals(obj.getClass()))
{
@@ -774,19 +833,102 @@
+ fields[0] + " to " + obj.getClass());
return;
}
+ count++;
for (int i = 0; i < fieldDescs.length; i++)
{
FieldDescriptor fd = fieldDescs[i];
PersistentField f = fd.getPersistentField();
- f.set(obj, fields[1 + i]);
+ f.set(obj, fields[count]);
+ count++;
}
- for (int i = 0; i < refDescs.length; i++)
+ for (Iterator it = refDescs.iterator(); it.hasNext(); count++)
{
- ObjectReferenceDescriptor rds = refDescs[i];
+ ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) it.next();
PersistentField f = rds.getPersistentField();
- f.set(obj, fields[1 + fieldDescs.length + i]);
+ Identity oid = (Identity) fields[count];
+ Object relObj;
+ if (oid == null)
+ {
+ relObj = null;
+ }
+ else
+ {
+ relObj = _pb.getObjectByIdentity(oid);
+ }
+ f.set(obj, relObj);
+ }
+
+ count = 0;
+ for (Iterator it = colDescs.iterator(); it.hasNext(); count++)
+ {
+ CollectionDescriptor cds = (CollectionDescriptor) it.next();
+ PersistentField f = cds.getPersistentField();
+ Class type = f.getType();
+ ArrayList list = collections[count];
+
+ if (list == null)
+ {
+ f.set(obj, null);
+ }
+ else
+ {
+ if (Collection.class.isAssignableFrom(type))
+ {
+ Collection col = (Collection) f.get(obj);
+
+ if (col == null)
+ {
+ if (type == List.class || type == Collection.class)
+ {
+ col = new ArrayList();
+ }
+ else if (type == Set.class)
+ {
+ col = new HashSet();
+ }
+ else
+ {
+ try
+ {
+ col = (Collection) type.newInstance();
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Cannot instantiate collection field: " + f);
+ ex.printStackTrace();
+ continue;
+ }
+ }
+ }
+ else
+ {
+ col.clear();
+ }
+ for (Iterator it2 = list.iterator(); it2.hasNext(); )
+ {
+ Identity relOid = (Identity) it2.next();
+ Object relObj = _pb.getObjectByIdentity(relOid);
+
+ if (relObj != null)
+ {
+ col.add(relObj);
+ }
+ }
+ }
+ else if (type.isArray())
+ {
+ int length = list.size();
+ Object array = Array.newInstance(type.getComponentType(), length);
+
+ for (int i = 0; i < length; i++)
+ {
+ Array.set(array, i, list.get(i));
+ }
+ f.set(obj, array);
+ }
+ }
}
}
@@ -848,6 +990,23 @@
return hasBidirAssc;
}
+ /*
+ * The rest of ObjectCache implementation for swizling
+ * All methods except lookup() are never used by swizzling,
+ * remove() appeared to already exist in this class
+ * with the same signature as in ObjectCache interface,
+ * other methods are unsupported.
+ */
+ public void cache(Identity oid, Object obj)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
//////////////////////////////////////////
// Inner classes
@@ -862,6 +1021,11 @@
* Handler the proxy object, null if the object is real
*/
IndirectionHandler handler;
+
+ /**
+ * This flag is used during commit/checkpoint
+ */
+ boolean needsCacheSwizzle;
ContextEntry(Object theObject)
{
1.13 +1 -1 db-ojb/src/java/org/apache/ojb/otm/kit/SimpleKit.java
Index: SimpleKit.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/kit/SimpleKit.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- SimpleKit.java 11 Jul 2003 19:30:26 -0000 1.12
+++ SimpleKit.java 13 Jul 2003 14:07:16 -0000 1.13
@@ -197,6 +197,6 @@
**/
public boolean isEagerInsert(Object obj)
{
- return false;
+ return false;
}
}
1.4 +120 -1 db-ojb/src/java/org/apache/ojb/otm/swizzle/CopySwizzling.java
Index: CopySwizzling.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/swizzle/CopySwizzling.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- CopySwizzling.java 28 Jun 2003 12:46:55 -0000 1.3
+++ CopySwizzling.java 13 Jul 2003 14:07:16 -0000 1.4
@@ -1,8 +1,15 @@
package org.apache.ojb.otm.swizzle;
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Iterator;
+import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.cache.ObjectCache;
import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.CollectionDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
/**
@@ -18,7 +25,8 @@
/**
* @see org.apache.ojb.otm.swizzle.Swizzling#swizzle(Object, Object, PersistenceBroker)
*/
- public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb)
+ public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb,
+ ObjectCache cache)
{
if (newObj == null) // invalidating
{
@@ -45,6 +53,117 @@
FieldDescriptor fd = fieldDescs[i];
PersistentField f = fd.getPersistentField();
f.set(oldObj, f.get(newObj));
+ }
+
+ // N:1 relations
+ Iterator iter = mif.getObjectReferenceDescriptors().iterator();
+ ObjectReferenceDescriptor rds;
+ PersistentField field;
+ Object newRelObj;
+ Identity newRelOid;
+ Object oldRelObj;
+
+ while (iter.hasNext())
+ {
+ rds = (ObjectReferenceDescriptor) iter.next();
+ field = rds.getPersistentField();
+ newRelObj = field.get(newObj);
+ oldRelObj = field.get(oldObj);
+ if ((newRelObj == null) && (oldRelObj != null))
+ {
+ field.set(oldObj, null);
+ }
+ else if (newRelObj != null)
+ {
+ newRelOid = new Identity(newRelObj, pb);
+ if ((oldRelObj == null) ||
+ !newRelOid.equals(new Identity(oldRelObj, pb)))
+ {
+ // seek for existing old object with the new identity
+ oldRelObj = cache.lookup(newRelOid);
+ if (oldRelObj == null)
+ {
+ oldRelObj = newRelObj;
+ }
+ field.set(oldObj, oldRelObj);
+ }
+ }
+ }
+
+ // 1:N relations
+ Iterator collections = mif.getCollectionDescriptors().iterator();
+ CollectionDescriptor collectionDescriptor;
+
+ while (collections.hasNext())
+ {
+ collectionDescriptor = (CollectionDescriptor) collections.next();
+ field = collectionDescriptor.getPersistentField();
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ Collection newCol;
+ Collection oldCol;
+
+ newCol = (Collection) field.get(newObj);
+ if (newCol == null)
+ {
+ field.set(oldObj, null);
+ continue;
+ }
+
+ oldCol = (Collection) field.get(oldObj);
+ if (oldCol == null)
+ {
+ try
+ {
+ oldCol = (Collection) newCol.getClass().newInstance();
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Cannot instantiate collection field which is neither Collection nor array: " + field);
+ ex.printStackTrace();
+ return newObj;
+ }
+ }
+ else
+ {
+ oldCol.clear();
+ }
+ for (Iterator it = newCol.iterator(); it.hasNext(); )
+ {
+ newRelObj = it.next();
+ newRelOid = new Identity(newRelObj, pb);
+ oldRelObj = cache.lookup(newRelOid);
+ if (oldRelObj == null)
+ {
+ oldRelObj = newRelObj;
+ }
+ oldCol.add(oldRelObj);
+ }
+ }
+ else if (field.getType().isArray())
+ {
+ Object newArray = field.get(newObj);
+ int length = Array.getLength(newArray);
+ Object oldArray =
+ Array.newInstance(field.getType().getComponentType(), length);
+
+ for (int i = 0; i < length; i++)
+ {
+ newRelObj = Array.get(newArray, i);
+ newRelOid = new Identity(newRelObj, pb);
+ oldRelObj = cache.lookup(newRelOid);
+ if (oldRelObj == null)
+ {
+ oldRelObj = newRelObj;
+ }
+ Array.set(oldArray, i, oldRelObj);
+ }
+ }
+ else
+ {
+ System.err.println("Cannot swizzle collection field: " + field);
+ return newObj;
+ }
}
return oldObj;
1.3 +2 -1 db-ojb/src/java/org/apache/ojb/otm/swizzle/NoSwizzling.java
Index: NoSwizzling.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/swizzle/NoSwizzling.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- NoSwizzling.java 12 Jun 2003 23:40:52 -0000 1.2
+++ NoSwizzling.java 13 Jul 2003 14:07:16 -0000 1.3
@@ -1,6 +1,7 @@
package org.apache.ojb.otm.swizzle;
import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.cache.ObjectCache;
/**
*
@@ -16,7 +17,7 @@
* @see org.apache.ojb.otm.swizzle.Swizzling#swizzle(Object, Object, PersistenceBroker)
*/
public Object swizzle(Object newObj, Object oldObj,
- PersistenceBroker pb)
+ PersistenceBroker pb, ObjectCache cache)
{
return newObj;
}
1.4 +7 -1 db-ojb/src/java/org/apache/ojb/otm/swizzle/Swizzling.java
Index: Swizzling.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/swizzle/Swizzling.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Swizzling.java 16 Jun 2003 22:47:27 -0000 1.3
+++ Swizzling.java 13 Jul 2003 14:07:16 -0000 1.4
@@ -1,6 +1,7 @@
package org.apache.ojb.otm.swizzle;
import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.cache.ObjectCache;
/**
*
@@ -23,10 +24,15 @@
* is null if no object is present
* @param pb the PersistenceBroker that is used to get
* persistent class info
+ * @param cache the "cache" of old objects, only lookup() method
+ * can be used by the Swizzling implementation to seek for old objects
+ * that should be set as a new value of relations
+ *
* @return the Swizzled Object
*
*/
- public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb);
+ public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb,
+ ObjectCache cache);
/**
*
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org