db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r495668 [2/2] - in /db/ojb/trunk: lib/ src/java/org/apache/ojb/broker/accesslayer/batch/ src/java/org/apache/ojb/broker/cache/ src/java/org/apache/ojb/broker/core/ src/java/org/apache/ojb/broker/metadata/ src/java/org/apache/ojb/broker/util...
Date Fri, 12 Jan 2007 18:06:11 GMT
Added: db/ojb/trunk/src/java/org/apache/ojb/broker/util/ConvertHelper.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/util/ConvertHelper.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/util/ConvertHelper.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/util/ConvertHelper.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,92 @@
+package org.apache.ojb.broker.util;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+
+/**
+ * Helper class to convert objects (e.g. String to Integer).
+ *
+ * @version $Id: $
+ */
+public class ConvertHelper
+{
+    private static Logger log = LoggerFactory.getLogger(ConvertHelper.class);
+
+    public static Integer toInteger(String value) throws NumberFormatException
+    {
+        try
+        {
+            return value != null ? new Integer(value) : null;
+        }
+        catch(NumberFormatException e)
+        {
+            log.error("Can't convert String '" + value + "' to Integer");
+            throw e;
+        }
+    }
+
+    public static int toIntegerPrimitiv(String value) throws NumberFormatException
+    {
+        try
+        {
+            return value != null ? Integer.parseInt(value) : 0;
+        }
+        catch(NumberFormatException e)
+        {
+            log.error("Can't convert String '" + value + "' to Integer");
+            throw e;
+        }
+    }
+
+    public static Long toLong(String value) throws NumberFormatException
+    {
+        try
+        {
+            return value != null ? new Long(value) : null;
+        }
+        catch(NumberFormatException e)
+        {
+            log.error("Can't convert String '" + value + "' to Long");
+            throw e;
+        }
+    }
+
+    public static long toLongPrimitiv(String value) throws NumberFormatException
+    {
+        try
+        {
+            return value != null ? Long.parseLong(value) : 0;
+        }
+        catch(NumberFormatException e)
+        {
+            log.error("Can't convert String '" + value + "' to Long");
+            throw e;
+        }
+    }
+
+    public static Boolean toBoolean(String value)
+    {
+        return BooleanUtils.toBooleanObject(value);
+    }
+
+    public static boolean toBooleanPrimitiv(String value)
+    {
+        return BooleanUtils.toBoolean(value);
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/util/IdentityHashSet.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/util/IdentityHashSet.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/util/IdentityHashSet.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/util/IdentityHashSet.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,94 @@
+package org.apache.ojb.broker.util;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.collections.map.IdentityMap;
+
+/**
+ * This is a object identity based {@link java.util.Set} implementation.
+ *
+ * @version $Id: $
+ */
+public class IdentityHashSet extends AbstractSet implements Set
+{
+    private static final Object DUMMY = new Object();
+    private org.apache.commons.collections.map.IdentityMap map;
+
+    public IdentityHashSet()
+    {
+        this(null);
+    }
+
+    public IdentityHashSet(Collection c)
+    {
+        map = new org.apache.commons.collections.map.IdentityMap();
+        if(c != null) addAll(c);
+    }
+
+    public Iterator iterator()
+    {
+        return map.keySet().iterator();
+    }
+
+    public int size()
+    {
+        return map.size();
+    }
+
+    public boolean isEmpty()
+    {
+        return map.isEmpty();
+    }
+
+    public boolean contains(Object o)
+    {
+        return map.containsKey(o);
+    }
+
+    public boolean add(Object o)
+    {
+        return map.put(o, DUMMY) == null;
+    }
+
+    public boolean remove(Object o)
+    {
+        return map.remove(o) == DUMMY;
+    }
+
+    public void clear()
+    {
+        map.clear();
+    }
+
+    public Object clone()
+    {
+        try
+        {
+            IdentityHashSet newSet = (IdentityHashSet) super.clone();
+            newSet.map = (IdentityMap) map.clone();
+            return newSet;
+        }
+        catch(CloneNotSupportedException e)
+        {
+            throw new RuntimeException("Unexpected error", e);
+        }
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/util/WeakIdentityList.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/util/WeakIdentityList.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/util/WeakIdentityList.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/util/WeakIdentityList.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,171 @@
+package org.apache.ojb.broker.util;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.Object;
+import java.lang.ref.WeakReference;
+import java.lang.ref.ReferenceQueue;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.AbstractList;
+import java.util.List;
+
+/**
+ * A object identity based (use '==' instead of 'equals' to compare objects) {@link java.util.List}
+ * with <em>weak</em> object entries (internal use of {@link java.lang.ref.WeakReference}).
+ *
+ * @version $Id: $
+ */
+public class WeakIdentityList extends AbstractList
+{
+    private List list;
+
+    /**
+     * Reference queue for weak references
+     */
+    private final ReferenceQueue queue = new ReferenceQueue();
+
+    public WeakIdentityList()
+    {
+        this(null, 20);
+    }
+
+    public WeakIdentityList(int initialCapacity)
+    {
+        this(null, initialCapacity);
+    }
+
+    public WeakIdentityList(Collection c)
+    {
+        this(c, c != null ? c.size() + 20 : 20);
+    }
+
+    public WeakIdentityList(Collection c, int initialCapacity)
+    {
+        list = new ArrayList(initialCapacity);
+        if(c != null)
+        {
+            addAll(c);
+        }
+    }
+
+    public Object get(int index)
+    {
+        Entry result = (Entry) list.get(index);
+        // pollQueue() call could corrupt internal used Iterator
+        return unwrap(result);
+    }
+
+    public Iterator iterator()
+    {
+        // poll before return Iterator
+        pollQueue();
+        return super.iterator();
+    }
+
+    public int size()
+    {
+        pollQueue();
+        return list.size();
+    }
+
+    public Object set(int index, Object element)
+    {
+        Entry result = (Entry) list.set(index, wrap(element));
+        // poll queue after set of object to avoid index error
+        pollQueue();
+        return unwrap(result);
+    }
+
+    public void add(int index, Object element)
+    {
+        list.add(index, wrap(element));
+        // poll queue after add of object to avoid index error
+        pollQueue();
+    }
+
+    public Object remove(int index)
+    {
+        return list.remove(index);
+    }
+
+    /**
+     * Poll reference queue.
+     */
+    private void pollQueue()
+    {
+        Object ref;
+        while((ref = queue.poll()) != null)
+        {
+            remove(ref);
+        }
+    }
+
+    private Entry wrap(Object obj)
+    {
+        if(obj == null)
+        {
+            throw new NullPointerException("Adding 'null' entries to list is not allowed");
+        }
+        return new Entry(obj, queue);
+    }
+
+    private Object unwrap(Entry e)
+    {
+        return e != null ? e.get() : null;
+    }
+
+    static class Entry extends WeakReference
+    {
+        public Entry(Object referent)
+        {
+            super(referent);
+        }
+
+        public Entry(Object referent, ReferenceQueue q)
+        {
+            super(referent, q);
+        }
+
+        public boolean equals(Object other)
+        {
+            boolean result = false;
+            Object current = get();
+            //Object other = obj != null ? ((WeakReference) obj).get() : null;
+            if(current != null)
+            {
+                if(other != null)
+                {
+                    result = current == other;
+                }
+            }
+            else
+            {
+                if(other == null)
+                {
+                    result = true;
+                }
+            }
+            return result;
+        }
+
+        public String toString()
+        {
+            return get() != null ? get().toString() : null;
+        }
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/util/collections/RemovalAwareVector.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/util/collections/RemovalAwareVector.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/util/collections/RemovalAwareVector.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/util/collections/RemovalAwareVector.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,138 @@
+package org.apache.ojb.broker.util.collections;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * This class
+ *
+ * @version $Id: $
+ */
+public class RemovalAwareVector extends ManageableVector implements TrackingCollection
+{
+    private Collection deletedObjects = new HashSet();
+    private Collection newObjects = new HashSet();
+
+    public Collection getDeletedObjects()
+    {
+        return deletedObjects;
+    }
+
+    public Collection getNewObjects()
+    {
+        return newObjects;
+    }
+
+    public void clearDeletedObjects()
+    {
+        deletedObjects.clear();
+    }
+
+    public void clearNewObjects()
+    {
+        newObjects.clear();
+    }
+
+
+
+    public void add(int index, Object element)
+    {
+        newObjects.add(element);
+        super.add(index, element);
+    }
+
+    public synchronized boolean add(Object o)
+    {
+        newObjects.add(o);
+        return super.add(o);
+    }
+
+    public synchronized boolean addAll(Collection c)
+    {
+        newObjects.addAll(c);
+        return super.addAll(c);
+    }
+
+    public synchronized boolean addAll(int index, Collection c)
+    {
+        newObjects.addAll(c);
+        return super.addAll(index, c);
+    }
+
+    public synchronized void addElement(Object obj)
+    {
+        newObjects.add(obj);
+        super.addElement(obj);
+    }
+
+    public synchronized Object remove(int index)
+    {
+        deletedObjects.add(get(index));
+        return super.remove(index);
+    }
+
+    public synchronized boolean removeAll(Collection c)
+    {
+        Iterator e = iterator();
+        while(e.hasNext())
+        {
+            Object o = e.next();
+            if(c.contains(o))
+            {
+                deletedObjects.add(o);
+            }
+        }
+        return super.removeAll(c);
+    }
+
+    public synchronized void removeAllElements()
+    {
+        Iterator it = iterator();
+        while(it.hasNext())
+        {
+            deletedObjects.add(it.next());
+        }
+        super.removeAllElements();
+    }
+
+    public synchronized boolean removeElement(Object obj)
+    {
+        boolean result = super.removeElement(obj);
+        if(result) deletedObjects.add(obj);
+        return result;
+    }
+
+    public synchronized void removeElementAt(int index)
+    {
+        deletedObjects.add(get(index));
+        super.removeElementAt(index);
+    }
+
+    protected void removeRange(int fromIndex, int toIndex)
+    {
+        // not supported
+        throw new UnsupportedOperationException("Not supported");
+    }
+
+    public synchronized boolean retainAll(Collection c)
+    {
+        // not supported
+        throw new UnsupportedOperationException("Not supported");
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/PerFieldManager.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/PerFieldManager.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/PerFieldManager.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/PerFieldManager.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,132 @@
+package org.apache.ojb.broker.util.sequence;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.accesslayer.JdbcAccess;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.SequenceDescriptor;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+
+/**
+ * A sequence manager implementation which handle per field sequence manager
+ * declarations.
+ *
+ * @version $Id: $
+ */
+public class PerFieldManager implements SequenceManager
+{
+    private Logger log = LoggerFactory.getLogger(this.getClass());
+
+    private Map fieldToManagerMap;
+    private SequenceManager defaultManager;
+
+    /**
+     * Constructor.
+     * @param defaultManager The default sequence manager instance used if no specific
+     * sequence manager ({@link org.apache.ojb.broker.metadata.SequenceDescriptor}) is set
+     * for the {@link org.apache.ojb.broker.metadata.FieldDescriptor}.
+     */
+    public PerFieldManager(SequenceManager defaultManager)
+    {
+        setDefaultManager(defaultManager);
+        log.info("Init per field sequence manager. Current set default manager is " + defaultManager);
+        fieldToManagerMap = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD);
+    }
+
+    /**
+     * Get the default manager.
+     */
+    public SequenceManager getDefaultManager()
+    {
+        return defaultManager;
+    }
+
+    /**
+     * Set the default manager instance used for all {@link org.apache.ojb.broker.metadata.FieldDescriptor}
+     * without specific {@link org.apache.ojb.broker.metadata.SequenceDescriptor}.
+     *
+     * @param defaultManager The default {@link SequenceManager} instance.
+     */
+    public void setDefaultManager(SequenceManager defaultManager)
+    {
+        if(log.isDebugEnabled()) log.debug("Set default sequence manager: " + defaultManager);
+        this.defaultManager = defaultManager;
+    }
+
+    public Object getUniqueValue(PersistenceBrokerInternal broker, FieldDescriptor field) throws SequenceManagerException
+    {
+        SequenceManager sm = lookup(broker, field);
+        return sm.getUniqueValue(broker, field);
+    }
+
+    public void afterStore(PersistenceBrokerInternal broker, JdbcAccess dbAccess, ClassDescriptor cld, Object obj) throws SequenceManagerException
+    {
+        FieldDescriptor[] pks = cld.getAutoIncrementFields();
+        FieldDescriptor result;
+        for(int i = 0; i < pks.length; i++)
+        {
+            result = pks[i];
+            SequenceManager sm = lookup(broker, result);
+            if(sm != null)
+            {
+                sm.afterStore(broker, dbAccess, cld, obj);
+            }
+        }
+    }
+
+    private SequenceManager lookup(PersistenceBrokerInternal broker, FieldDescriptor field)
+    {
+        SequenceManager sm = (SequenceManager) fieldToManagerMap.get(field);
+        if(sm == null && field.isAutoIncrement())
+        {
+            SequenceDescriptor sd = field.getSequenceDescriptor();
+            if(sd != null)
+            {
+                if(log.isDebugEnabled())
+                {
+                    ClassDescriptor cld = field.getClassDescriptor();
+                    log.debug("Create field specific sequence manager for field '"
+                            + field.getPersistentField().getName()
+                            + "' of class '"
+                            + (cld != null ? cld.getClassNameOfObject() : "null")
+                            + "', using sequence descriptor=" + sd);
+                }
+                sm = SequenceManagerHelper.createManager(broker.serviceConnectionManager().getSupportedPlatform(), sd);
+            }
+            else
+            {
+                if(log.isDebugEnabled())
+                {
+                    ClassDescriptor cld = field.getClassDescriptor();
+                    log.debug("Use default sequence manager for field '"
+                                + field.getPersistentField().getName()
+                                + "' of class '"
+                                + (cld != null ? cld.getClassNameOfObject() : "null")
+                                + "'");
+                }
+                sm = defaultManager;
+            }
+            fieldToManagerMap.put(field, sm);
+        }
+        return sm;
+    }
+}

Added: db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerIdentityImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerIdentityImpl.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerIdentityImpl.java (added)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerIdentityImpl.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,225 @@
+package org.apache.ojb.broker.util.sequence;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.platforms.Platform;
+import org.apache.ojb.broker.accesslayer.JdbcAccess;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.SequenceDescriptor;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
+
+/**
+ * Sequence manager implementation using native database <tt>Identity columns</tt>
+ * (like MySQL, MSSQL, ...). For proper work some specific metadata settings
+ * needed:
+ * <ul>
+ * <li>field representing the identity column need attribute <code>autoincrement</code> 'true'</li>
+ * <li>field representing the identity column need attribute <code>access</code> set 'readonly'</li>
+ * <li>field representing the identity column need attribute <code>primarykey</code> set 'true'</li>
+ * <li>only possible to declare one identity field per class</li>
+ * </ul>
+ * <p/>
+ * <b>Note:</b>
+ * Make sure that the DB generated identity columns represent values &gt 0, because negative values
+ * intern used by this implementation and 0 could cause problems with primitive FK fields.
+ * </p>
+ * <p/>
+ * Implementation configuration properties:
+ * <table cellspacing="2" cellpadding="2" border="3" frame="box">
+ * <tr>
+ * <td><strong>Property Key</strong></td>
+ * <td><strong>Property Values</strong></td>
+ * </tr>
+ * <tr>
+ * <td>no properties to set</td>
+ * <td>
+ * <p/>
+ * </td>
+ * </tr>
+ * </table>
+ * </p>
+ * <p/>
+ * <p/>
+ * <b>Limitations:</b>
+ * <ul>
+ * <li>Native key generation is not 'extent aware'
+ * when extent classes span several tables! Please
+ * see more in shipped docs 'extents and polymorphism'
+ * or sequence manager docs.
+ * </li>
+ * <li>
+ * Only positive identity values are allowed (see above).
+ * </li>
+ * </ul>
+ * </p>
+ * <br/>
+ *
+ * @version $Id: SequenceManagerIdentityImpl.java 432648 2006-08-18 19:18:37 +0200 (Fr, 18 Aug 2006) arminw $
+ */
+public class SequenceManagerIdentityImpl extends AbstractSequenceManager
+{
+    private Log log = LogFactory.getLog(SequenceManagerIdentityImpl.class);
+
+    /*
+     TODO:
+     1. Find a better solution (if possible) for this problem
+     We need this dummy field to return a negative long value
+     on getUniqueLong(...) call. If we return always the same
+     value, the resulting Identity object was found on cache.
+
+     2. Problem is that generated oid (by Identity column)
+     must not begin with 0.
+
+     Use keyword 'volatile' to make decrement of a long value an
+     atomic operation
+     */
+    private static volatile long tempKey = -1;
+
+    public SequenceManagerIdentityImpl(Platform platform, SequenceDescriptor descriptor)
+    {
+        super(platform, descriptor);
+    }
+
+    public void afterStore(PersistenceBrokerInternal broker, JdbcAccess dbAccess, ClassDescriptor cld, Object obj)
+            throws SequenceManagerException
+    {
+        // if database Identity Columns are used, query the id from database
+        // thus we have to execute batch entries before
+        broker.serviceBatchManager().executeBatch();
+        FieldDescriptor identityField = extractIdentityColumnField(cld);
+        if(identityField != null)
+        {
+            ifNotReadOnlyFail(identityField);
+            long newId = getLastInsert(broker, cld, identityField);
+            setFieldValue(obj, identityField, new Long(newId));
+        }
+    }
+
+    /**
+     * Gets the identity column descriptor for the given class
+     * or return <code>null</code> if none defined.
+     *
+     * @param cld The class descriptor
+     * @return The class's identity column or <code>null</code> if it does not have one
+     */
+    private FieldDescriptor extractIdentityColumnField(ClassDescriptor cld)
+    {
+        FieldDescriptor[] pkFields = cld.getAutoIncrementFields();
+        for(int i = 0; i < pkFields.length; i++)
+        {
+            // to find the identity column we search for a autoincrement
+            // read-only field
+            if(pkFields[i].isAccessReadOnly())
+            {
+                return pkFields[i];
+            }
+        }
+        return null;
+    }
+
+    private void ifNotReadOnlyFail(FieldDescriptor field) throws SequenceManagerException
+    {
+        // is field declared as read-only?
+        if(!field.isAccessReadOnly())
+        {
+            throw new SequenceManagerException("Can't find Identity column: Identity columns/fields need to be declared as" +
+                    " 'autoincrement' with 'readonly' access in field-descriptor");
+        }
+    }
+
+    private long getLastInsert(PersistenceBrokerInternal broker, ClassDescriptor cld, FieldDescriptor field) throws SequenceManagerException
+    {
+        long newId = 0;
+        Statement stmt = null;
+        if(field != null)
+        { // an autoinc column exists
+            try
+            {
+                stmt = broker.serviceConnectionManager().getConnection().createStatement();
+                ResultSet rs = stmt.executeQuery(lastInsertSelect(broker, cld.getFullTableName()));
+                if(!rs.next())
+                {
+                    throw new SequenceManagerException("Could not find native identifier");
+                }
+                newId = rs.getLong(1);
+                rs.close();
+                if(log.isDebugEnabled()) log.debug("After store - newid=" + newId);
+            }
+            catch(Exception e)
+            {
+                throw new SequenceManagerException(
+                        "Error while execute query: " + lastInsertSelect(broker, cld.getFullTableName()), e);
+            }
+            finally
+            {
+                try
+                {
+                    if(stmt != null) stmt.close();
+                }
+                catch(SQLException e)
+                {
+                    if(log.isDebugEnabled())
+                        log.debug("Threw SQLException while in getLastInsert and closing stmt", e);
+                    // ignore it
+                }
+            }
+        }
+        else
+        {
+            throw new SequenceManagerException("No autoincrement field declared, please check repository for " + cld);
+        }
+        return newId;
+    }
+
+    /*
+     * query for the last insert id.
+     */
+    protected String lastInsertSelect(PersistenceBrokerInternal broker, String tableName)
+    {
+        return broker.serviceConnectionManager().
+                getSupportedPlatform().getLastInsertIdentityQuery(tableName);
+    }
+
+    private void setFieldValue(Object obj, FieldDescriptor field, Long identifier) throws SequenceManagerException
+    {
+        Object result = field.getJdbcType().sequenceKeyConversion(identifier);
+        result = field.getFieldConversion().sqlToJava(result);
+        PersistentField pf = field.getPersistentField();
+        pf.set(obj, result);
+    }
+
+    /**
+     * returns a negative value
+     */
+    protected long getUniqueLong(PersistenceBrokerInternal broker, FieldDescriptor field) throws SequenceManagerException
+    {
+        /*
+        arminw:
+        workaround for locking problems of new objects
+        We need unique 'dummy keys' for new objects before storing.
+        Variable 'tempKey' is declared volatile, thus decrement should be atomic
+        */
+        return --tempKey;
+    }
+}

Added: db/ojb/trunk/src/test/org/apache/ojb/broker/BatchStrategyTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/BatchStrategyTest.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/BatchStrategyTest.java (added)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/BatchStrategyTest.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,388 @@
+package org.apache.ojb.broker;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ojb.junit.PBTestCase;
+import org.apache.ojb.broker.accesslayer.batch.BatchStrategy;
+import org.apache.ojb.broker.accesslayer.batch.BatchManager;
+import org.apache.ojb.broker.accesslayer.batch.Batcher;
+import org.apache.ojb.broker.accesslayer.batch.BatchListener;
+import org.apache.ojb.broker.accesslayer.batch.BatchStrategyDefaultImpl;
+import org.apache.ojb.broker.accesslayer.sql.SqlInsertStatement;
+import org.apache.ojb.broker.accesslayer.sql.SqlUpdateStatement;
+import org.apache.ojb.broker.accesslayer.sql.SqlDeleteByPkStatement;
+import org.apache.ojb.broker.core.ValueContainer;
+import org.apache.ojb.broker.util.ClassHelper;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.platforms.Platform;
+
+/**
+ * Test batch strategy implementation.
+ */
+public class BatchStrategyTest extends PBTestCase
+{
+    public static void main(String[] args)
+    {
+        String[] arr = {BatchStrategyTest.class.getName()};
+        junit.textui.TestRunner.main(arr);
+    }
+
+    public BatchStrategyTest(String testName)
+    {
+        super(testName);
+    }
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+
+    }
+
+    public void testMultipleObject() throws Exception
+    {
+        doMultipleObject(BatchStrategyDefaultImpl.class);
+    }
+
+    public void doMultipleObject(Class strategyClass) throws Exception
+    {
+        TestBatchManager bm = new TestBatchManager();
+        BatchStrategy strategy = createStrategy(strategyClass, bm);
+        bm.setStrategy(strategy);
+        Platform pf = broker.serviceConnectionManager().getSupportedPlatform();
+        Logger log = new NoopLogger();
+
+        ValueContainer[] empty = new ValueContainer[]{};
+        ClassDescriptor cld = broker.getClassDescriptor(Person.class);
+        ClassDescriptor cldOther = broker.getClassDescriptor(Zoo.class);
+
+        String sqlInsert = (new SqlInsertStatement(pf, log, cld)).getStatement();
+        String sqlUpdate = (new SqlUpdateStatement(pf, log, cld)).getStatement();
+        String sqlDelete = (new SqlDeleteByPkStatement(pf, log, cld)).getStatement();
+
+        String sqlInsertOther = (new SqlInsertStatement(pf, log, cldOther)).getStatement();
+        String sqlUpdateOther = (new SqlUpdateStatement(pf, log, cldOther)).getStatement();
+        String sqlDeleteOther = (new SqlDeleteByPkStatement(pf, log, cldOther)).getStatement();
+
+        Batcher b_insert = new Batcher.Insert(cld, cld.getInsertProcedure(), sqlInsert);
+        Batcher b_update = new Batcher.Update(cld, cld.getUpdateProcedure(), sqlUpdate);
+        Batcher b_delete = new Batcher.Delete(cld, cld.getDeleteProcedure(), sqlDelete);
+
+        Batcher b_insertOther = new Batcher.Insert(cldOther, cldOther.getInsertProcedure(), sqlInsertOther);
+        Batcher b_updateOther = new Batcher.Update(cldOther, cldOther.getUpdateProcedure(), sqlUpdateOther);
+        Batcher b_deleteOther = new Batcher.Delete(cldOther, cldOther.getDeleteProcedure(), sqlDeleteOther);
+
+
+        bm.add(b_insertOther, empty, 1);
+        bm.add(b_updateOther, empty, 1);
+        assertEquals(2, bm.getBatchEntities().size());
+
+        bm.add(b_update, empty, 1);
+        bm.add(b_delete, empty, 1);
+        assertEquals(4, bm.getBatchEntities().size());
+
+        bm.add(b_deleteOther, empty, 1);
+        assertEquals(4, bm.getBatchEntities().size());
+
+        bm.add(b_insert, empty, 1);
+        assertEquals(2, bm.getBatchEntities().size());
+
+        bm.executeBatch();
+    }
+
+    public void testSingleObject() throws Exception
+    {
+        doSingleObject(BatchStrategyDefaultImpl.class);
+    }
+
+    public void doSingleObject(Class strategyClass) throws Exception
+    {
+        TestBatchManager bm = new TestBatchManager();
+        BatchStrategy strategy = createStrategy(strategyClass, bm);
+        bm.setStrategy(strategy);
+        Platform pf = broker.serviceConnectionManager().getSupportedPlatform();
+        Logger log = new NoopLogger();
+
+
+        ValueContainer[] empty = new ValueContainer[]{};
+        ClassDescriptor cld = broker.getClassDescriptor(Person.class);
+
+        String sqlInsert = (new SqlInsertStatement(pf, log, cld)).getStatement();
+        String sqlUpdate = (new SqlUpdateStatement(pf, log, cld)).getStatement();
+        String sqlDelete = (new SqlDeleteByPkStatement(pf, log, cld)).getStatement();
+
+        Batcher b_insert = new Batcher.Insert(cld, cld.getInsertProcedure(), sqlInsert);
+        Batcher b_update = new Batcher.Update(cld, cld.getUpdateProcedure(), sqlUpdate);
+        Batcher b_delete = new Batcher.Delete(cld, cld.getDeleteProcedure(), sqlDelete);
+
+        bm.add(b_insert, empty, 1);
+        bm.add(b_insert, empty, 1);
+        bm.add(b_insert, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+
+        bm.add(b_delete, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+        bm.add(b_update, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+
+        bm.executeBatch();
+
+        bm.add(b_delete, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+        bm.add(b_update, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+        bm.add(b_insert, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+
+        bm.executeBatch();
+
+        bm.add(b_insert, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+        bm.add(b_update, empty, 1);
+        assertEquals(2, bm.getBatchEntities().size());
+
+        bm.executeBatch();
+
+        bm.add(b_update, empty, 1);
+        assertEquals(1, bm.getBatchEntities().size());
+        bm.add(b_delete, empty, 1);
+        assertEquals(2, bm.getBatchEntities().size());
+    }
+
+    private BatchStrategy createStrategy(Class strategy, BatchManager bm) throws Exception
+    {
+        return (BatchStrategy) ClassHelper.newInstance(
+                strategy, BatchManager.class, bm);
+    }
+
+    static class TestBatchManager implements BatchManager
+    {
+        int addCount;
+        int executeBatchCount;
+        BatchStrategy strategy;
+        List batchEntities = new ArrayList();
+
+        public int getAddCount()
+        {
+            return addCount;
+        }
+
+        public int getExecuteBatchCount()
+        {
+            return executeBatchCount;
+        }
+
+        public List getBatchEntities()
+        {
+            return batchEntities;
+        }
+
+        public void add(Batcher batcher, ValueContainer[] values, int expectedResult) throws SQLException
+        {
+            //System.out.println("* add(...)");
+            ++addCount;
+            Batcher entity = checkForExistingBatcher(batcher);
+            if(entity == null)
+            {
+                entity = batcher;
+                // lookup batch strategy and ask for updated (reordered, reduced, ...)
+                // list of batch entities
+                batchEntities = strategy.prepareForBatch(batchEntities, batcher);
+            }
+            entity.add(values, expectedResult);
+        }
+
+        private Batcher checkForExistingBatcher(Batcher newBatcher)
+        {
+            for(int i = 0; i < batchEntities.size(); i++)
+            {
+                Batcher batcher = (Batcher) batchEntities.get(i);
+                if(batcher.equals(newBatcher))
+                {
+                    return batcher;
+                }
+            }
+            return null;
+        }
+
+        public void executeBatch() throws PersistenceBrokerException
+        {
+            System.out.println("* executeBatch()");
+            batchEntities.clear();
+        }
+
+        public void executeBatch(Batcher batcher) throws PersistenceBrokerException
+        {
+            System.out.println("* executeBatch(batcher): " + batcher);
+            ++executeBatchCount;
+        }
+
+        public void cancelBatch()
+        {
+        }
+
+        public void addBatchListener(BatchListener listener)
+        {
+        }
+
+        public void removeBatchListener(BatchListener listener)
+        {
+        }
+
+        public void reset()
+        {
+        }
+
+        public void setBatchMode(boolean mode)
+        {
+        }
+
+        public boolean isBatchMode()
+        {
+            return false;
+        }
+
+        public void setBatchSupportOptimisticLocking(boolean batchOptimisticLocking)
+        {
+        }
+
+        public boolean getBatchSupportOptimisticLocking()
+        {
+            return false;
+        }
+
+        public void setBatchLimit(int limit)
+        {
+        }
+
+        public int getBatchLimit()
+        {
+            return 1000;
+        }
+
+        public BatchStrategy getStrategy()
+        {
+            return strategy;
+        }
+
+        public void setStrategy(BatchStrategy strategy)
+        {
+            this.strategy = strategy;
+        }
+    }
+
+    static class NoopLogger implements Logger
+    {
+        public void debug(Object pObject)
+        {
+        }
+
+        public void info(Object pObject)
+        {
+        }
+
+        public void warn(Object pObject)
+        {
+        }
+
+        public void error(Object pObject)
+        {
+        }
+
+        public void fatal(Object pObject)
+        {
+        }
+
+        public void debug(Object message, Throwable obj)
+        {
+        }
+
+        public void info(Object message, Throwable obj)
+        {
+        }
+
+        public void warn(Object message, Throwable obj)
+        {
+        }
+
+        public void error(Object message, Throwable obj)
+        {
+        }
+
+        public void fatal(Object message, Throwable obj)
+        {
+        }
+
+        public boolean isEnabledFor(int priority)
+        {
+            return false;
+        }
+
+        public boolean isDebugEnabled()
+        {
+            return false;
+        }
+
+        public String getName()
+        {
+            return null;
+        }
+
+        public void safeDebug(String message, Object obj)
+        {
+        }
+
+        public void safeDebug(String message, Object obj, Throwable t)
+        {
+        }
+
+        public void safeInfo(String message, Object obj)
+        {
+        }
+
+        public void safeInfo(String message, Object obj, Throwable t)
+        {
+        }
+
+        public void safeWarn(String message, Object obj)
+        {
+        }
+
+        public void safeWarn(String message, Object obj, Throwable t)
+        {
+        }
+
+        public void safeError(String message, Object obj)
+        {
+        }
+
+        public void safeError(String message, Object obj, Throwable t)
+        {
+        }
+
+        public void safeFatal(String message, Object obj)
+        {
+        }
+
+        public void safeFatal(String message, Object obj, Throwable t)
+        {
+        }
+    }
+}

Added: db/ojb/trunk/src/test/org/apache/ojb/broker/OneToOneWithoutFKTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/OneToOneWithoutFKTest.java?view=auto&rev=495668
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/OneToOneWithoutFKTest.java (added)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/OneToOneWithoutFKTest.java Fri Jan 12 10:06:09 2007
@@ -0,0 +1,354 @@
+package org.apache.ojb.broker;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.apache.ojb.junit.PBTestCase;
+import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
+import org.apache.ojb.broker.util.ObjectModification;
+
+/**
+ * This class show handling of bidirectional 1:1 reference without
+ * using a separate FK column (the PK of the main object is the FK too and the both objects use
+ * the same PK value).
+ * NOTE: It's not recommended to use 1:1 references without FK column.
+ *
+ * @version $Id: $
+ */
+public class OneToOneWithoutFKTest extends PBTestCase
+{
+    public static void main(String[] args)
+    {
+        String[] arr = {OneToOneWithoutFKTest.class.getName()};
+        junit.textui.TestRunner.main(arr);
+    }
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+    }
+
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+    }
+
+    /**
+     * Handle Person object without using a reference to Passport class.
+     */
+    public void testInsertUpdateDeletePerson()
+    {
+        ojbChangeReferenceSetting(Passport.class, "person",
+                true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_NONE, true);
+        ojbChangeReferenceSetting(Person.class, "passport",
+                true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, true);
+        String t = "_" + System.currentTimeMillis();
+        String name = "Person_testInsertUpdateDeletePerson_" + t;
+        assertTrue(broker.getClassDescriptor(Person.class).getObjectReferenceDescriptorByName("passport").isLazy());
+        assertTrue(broker.getClassDescriptor(Passport.class).getObjectReferenceDescriptorByName("person").isLazy());
+
+
+        Person pers = new Person(name);
+
+        broker.beginTransaction();
+        // store plain Person
+        broker.store(pers, ObjectModification.INSERT);
+        broker.commitTransaction();
+        // clear cache to check DB entry
+        broker.clearCache();
+        // lookup
+        Identity oid = broker.serviceIdentity().buildIdentity(Person.class, pers.getId());
+        Person pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+
+        broker.beginTransaction();
+        pers_new.setName(name + "_updated");
+        // store plain Person
+        broker.store(pers_new, ObjectModification.UPDATE);
+        broker.commitTransaction();
+        // clear cache to check DB entry
+        broker.clearCache();
+        // lookup
+        oid = broker.serviceIdentity().buildIdentity(Person.class, pers_new.getId());
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+        assertEquals(name+"_updated", pers_new.getName());
+        // NOTE: You try to access the none existing Passport object
+        // always null will be returned
+        assertNull(pers_new.getPassport().getId());
+        assertNull(pers_new.getPassport().getNumber());
+        assertNull(pers_new.getPassport().getPerson());
+
+
+        broker.beginTransaction();
+        // delete plain Person
+        broker.delete(pers);
+        broker.commitTransaction();
+        // lookup
+        oid = broker.serviceIdentity().buildIdentity(Person.class, pers_new.getId());
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNull(pers_new);
+    }
+
+    /**
+     * Handle Person <---> Passport objects with enabled proxy
+     */
+    public void testInsertUpdateDelete()
+    {
+        // metadata settings
+        // the main object Person use cascade update/delete, the dependend object not.
+        // For both 1:1 references proxy object are enabled.
+        ojbChangeReferenceSetting(Passport.class, "person",
+                true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_NONE, true);
+        ojbChangeReferenceSetting(Person.class, "passport",
+                true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, true);
+        String t = "_" + System.currentTimeMillis();
+        String name = "Person_testInsertUpdateDelete_" + t;
+        String number = "Passport_testInsertUpdateDelete_" + t;
+        assertTrue(broker.getClassDescriptor(Person.class).getObjectReferenceDescriptorByName("passport").isLazy());
+        assertTrue(broker.getClassDescriptor(Passport.class).getObjectReferenceDescriptorByName("person").isLazy());
+
+        // insert
+        Person pers = new Person(name);
+        Passport pass = new Passport(number);
+        broker.beginTransaction();
+        // store plain Person to assign PK
+        broker.store(pers);
+        // set PK/FK of Passport
+        pass.setId(pers.getId());
+        // set references
+        pers.setPassport(pass);
+        pass.setPerson(pers);
+        broker.store(pers);
+        broker.commitTransaction();
+
+        // lookup
+        Identity oid = broker.serviceIdentity().buildIdentity(pers);
+        Person pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+        assertNotNull(pers_new.getPassport());
+
+        // update
+        broker.beginTransaction();
+        pers_new.setName(name + "_updated");
+        pers_new.getPassport().setNumber(number + "_updated");
+        broker.store(pers_new);
+        broker.commitTransaction();
+
+        // lookup
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+        assertNotNull(pers_new.getPassport());
+        assertEquals(name + "_updated", pers_new.getName());
+        assertEquals(number + "_updated", pers_new.getPassport().getNumber());
+
+        // update nullify reference, with proxy references enabled, this result
+        // in unexpected proxy placeholder intead of null reference
+        broker.beginTransaction();
+        broker.delete(pers_new.getPassport());
+        pers_new.setPassport(null);
+        broker.store(pers_new);
+        broker.commitTransaction();
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+        // we alway get a proxy placeholder object
+        // assertNull(pers_new.getPassport());
+        assertNull(pers_new.getPassport().getId());
+        assertEquals(name + "_updated", pers_new.getName());
+
+        // delete
+        broker.beginTransaction();
+        // first delete the object with constraint
+        broker.delete(pers_new.getPassport());
+        // not needed, but this reduce the number of generated queries
+        pers_new.setPassport(null);
+        broker.delete(pers_new);
+        broker.commitTransaction();
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNull(pers_new);
+    }
+
+    /**
+     * Handle Person <---> Passport objects withot proxy
+     */
+    public void testInsertUpdateDelete_2()
+    {
+        // metadata settings
+        // the main object Person use cascade update/delete, the dependend object not.
+        // For both 1:1 references proxy references are disabled.
+        ojbChangeReferenceSetting(Passport.class, "person",
+                true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_NONE, false);
+        ojbChangeReferenceSetting(Person.class, "passport",
+                true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
+        String t = "_" + System.currentTimeMillis();
+        String name = "Person_testInsertUpdateDelete_2_" + t;
+        String number = "Passport_testInsertUpdateDelete_2_" + t;
+        assertFalse(broker.getClassDescriptor(Person.class).getObjectReferenceDescriptorByName("passport").isLazy());
+        assertFalse(broker.getClassDescriptor(Passport.class).getObjectReferenceDescriptorByName("person").isLazy());
+
+        // insert
+        Person pers = new Person(name);
+        Passport pass = new Passport(number);
+        broker.beginTransaction();
+        // store plain Person to assign PK
+        broker.store(pers);
+        // set PK/FK of Passport
+        pass.setId(pers.getId());
+        // set references
+        pers.setPassport(pass);
+        pass.setPerson(pers);
+        broker.store(pers);
+        broker.commitTransaction();
+
+        // lookup
+        Identity oid = broker.serviceIdentity().buildIdentity(pers);
+        Person pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+        assertNotNull(pers_new.getPassport());
+        assertNotNull(pers_new.getPassport().getPerson());
+
+        // update
+        broker.beginTransaction();
+        pers_new.setName(name + "_updated");
+        pers_new.getPassport().setNumber(number + "_updated");
+        broker.store(pers_new);
+        broker.commitTransaction();
+
+        // lookup
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNotNull(pers_new);
+        assertNotNull(pers_new.getPassport());
+        assertEquals(name + "_updated", pers_new.getName());
+        assertEquals(number + "_updated", pers_new.getPassport().getNumber());
+
+        // update nullify reference, with proxy references enabled, this result
+        // in unexpected proxy placeholder intead of null reference
+        broker.beginTransaction();
+        broker.delete(pers_new.getPassport());
+        pers_new.setPassport(null);
+        broker.store(pers_new);
+        broker.commitTransaction();
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNull(pers_new.getPassport());
+        assertEquals(name + "_updated", pers_new.getName());
+
+        // delete
+        broker.beginTransaction();
+        // first delete the object with constraint
+        broker.delete(pers_new.getPassport());
+        // not needed, but this reduce the number of generated queries
+        pers_new.setPassport(null);
+        broker.delete(pers_new);
+        broker.commitTransaction();
+        pers_new = (Person) broker.getObjectByIdentity(oid);
+        assertNull(pers_new);
+    }
+
+
+
+    public static class Person implements Serializable
+    {
+        private Integer id;
+        private String name;
+        private Passport passport;
+
+        public Person()
+        {
+        }
+
+        public Person(String name)
+        {
+            this.name = name;
+        }
+
+        public Integer getId()
+        {
+            return id;
+        }
+
+        public void setId(Integer id)
+        {
+            this.id = id;
+        }
+
+        public String getName()
+        {
+            return name;
+        }
+
+        public void setName(String name)
+        {
+            this.name = name;
+        }
+
+        public Passport getPassport()
+        {
+            return passport;
+        }
+
+        public void setPassport(Passport passport)
+        {
+            this.passport = passport;
+        }
+    }
+
+    public static class Passport implements Serializable
+    {
+        private Integer id;
+        private String number;
+        private Person person;
+
+        public Passport()
+        {
+        }
+
+        public Passport(String number)
+        {
+            this.number = number;
+        }
+
+        public Integer getId()
+        {
+            return id;
+        }
+
+        public void setId(Integer id)
+        {
+            this.id = id;
+        }
+
+        public String getNumber()
+        {
+            return number;
+        }
+
+        public void setNumber(String number)
+        {
+            this.number = number;
+        }
+
+        public Person getPerson()
+        {
+            return person;
+        }
+
+        public void setPerson(Person person)
+        {
+            this.person = person;
+        }
+    }
+}



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