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 br...@apache.org on 2006/02/15 19:19:59 UTC

svn commit: r378046 - in /db/ojb/branches/OJB_1_0_RELEASE: ./ src/java/org/apache/ojb/broker/accesslayer/ src/java/org/apache/ojb/broker/accesslayer/sql/ src/java/org/apache/ojb/broker/core/ src/java/org/apache/ojb/broker/metadata/ src/java/org/apache/...

Author: brj
Date: Wed Feb 15 10:19:56 2006
New Revision: 378046

URL: http://svn.apache.org/viewcvs?rev=378046&view=rev
Log:
Relationships based on non primarykey fields.
backport from ojb 1.x.

Added:
    db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/NoPkReferenceTest.java
Modified:
    db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/BrokerHelper.java
    db/ojb/branches/OJB_1_0_RELEASE/src/schema/ojbtest-schema.xml
    db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository.dtd
    db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository_junit.xml

Modified: db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt Wed Feb 15 10:19:56 2006
@@ -26,7 +26,67 @@
   the ojb quoting character is '. this character is replaced with the platform
   specific character when generating the sql. 
   'myTable' will be converted to "myTable", [myTable] etc. depending on Platform#getQuotedName
+- Relationships based on non primarykey fields. These fields are defined in the new 
+  attribute "target-field-ref" of inverse-foreignkey and foreignkey in collection- and
+  referenceDescriptor. If the target-field-ref is missing the primary key of the referenced
+  class is used.
+  
+     <class-descriptor
+         class="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
+         table="Artikel_2" >
+      <field-descriptor
+         name="articleId"
+         column="Artikel_Nr"
+         jdbc-type="INTEGER"
+         primarykey="true"
+         autoincrement="true"
+      />
+	  ...
+      <field-descriptor
+         name="productGroupName"
+         column="KatName"
+         jdbc-type="VARCHAR"
+      />
+	  ...
+      <reference-descriptor
+            name="productGroup"
+            class-ref="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
+      >
+         <foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
+      </reference-descriptor>
+   </class-descriptor>
 
+   <class-descriptor
+         class="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
+         table="Kategorien_2" >
+      <field-descriptor
+         name="groupId"
+         column="Kategorie_Nr"
+         jdbc-type="INTEGER"
+         primarykey="true"
+         autoincrement="true"
+      />
+      <field-descriptor
+         name="groupName"
+         column="Kategorie_Name"
+         jdbc-type="VARCHAR"
+      />
+      <field-descriptor
+         name="description"
+         column="Beschreibung"
+         jdbc-type="VARCHAR"
+      />
+      <collection-descriptor
+         name="allArticlesInGroup"
+		 element-class-ref="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
+         auto-retrieve="true"
+         auto-update="true"
+         auto-delete="false"
+      >
+         <inverse-foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
+      </collection-descriptor>
+   </class-descriptor>
+   
 NOTES:
 - OJB.properties file changed, replace it when update.
 - Documentation update and improvement: section about using RowReader and using a

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java Wed Feb 15 10:19:56 2006
@@ -84,7 +84,8 @@
         while (iter.hasNext())
         {
             owner = iter.next();
-            fkValues = helper.extractValueArray(helper.getKeyValues(cld, owner));
+            fkValues = getFkTargetValuesForObject(owner);
+
             id = getBroker().serviceIdentity().buildIdentity(null, topLevelClass, fkValues);
             idsSubset.add(id);
             if (idsSubset.size() == pkLimit)
@@ -142,7 +143,9 @@
         for (Iterator it = owners.iterator(); it.hasNext();)
         {
             Object owner = it.next();
-            ownerIdsToLists.put(identityFactory.buildIdentity(getOwnerClassDescriptor(), owner), new ArrayList());
+            Object[] targetValues = getFkTargetValuesForObject(owner);
+            Identity ownerId = identityFactory.buildIdentity(null, ownerTopLevelClass, targetValues);
+            ownerIdsToLists.put(ownerId, new ArrayList());
         }
 
         // build the children lists for the owners
@@ -152,7 +155,7 @@
             // BRJ: use cld for real class, relatedObject could be Proxy
             ClassDescriptor cld = getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(child));
 
-            Object[] fkValues = cds.getForeignKeyValues(child, cld);
+            Object[] fkValues = getFkValuesForObject(child);             
             Identity ownerId = identityFactory.buildIdentity(null, ownerTopLevelClass, fkValues);
             List list = (List) ownerIdsToLists.get(ownerId);
             if (list != null)
@@ -166,7 +169,8 @@
         {
             Object result;
             Object owner = it.next();
-            Identity ownerId = identityFactory.buildIdentity(owner);
+            Object[] targetValues = getFkTargetValuesForObject(owner);
+            Identity ownerId = identityFactory.buildIdentity(null, ownerTopLevelClass, targetValues);
             List list = (List) ownerIdsToLists.get(ownerId);
 
             if ((collectionClass == null) && field.getType().isArray())

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java Wed Feb 15 10:19:56 2006
@@ -26,6 +26,7 @@
 import org.apache.ojb.broker.cache.ObjectCache;
 import org.apache.ojb.broker.core.PersistenceBrokerImpl;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
 import org.apache.ojb.broker.query.Query;
@@ -70,13 +71,15 @@
         for (Iterator it = children.iterator(); it.hasNext(); )
         {
             relatedObject = it.next();
-            childrenMap.put(pb.serviceIdentity().buildIdentity(relatedObject), relatedObject);
+            Object[] targetValues = getFkTargetValuesForObject(relatedObject);
+            id = pb.serviceIdentity().buildIdentity(null, topLevelClass, targetValues);
+            childrenMap.put(id, relatedObject);
         }
 
         for (Iterator it = owners.iterator(); it.hasNext(); )
         {
             owner = it.next();
-            fkValues = ord.getForeignKeyValues(owner,cld);
+            fkValues = getFkValuesForObject(owner);
             if (isNull(fkValues))
             {
                 field.set(owner, null);
@@ -122,7 +125,7 @@
         while (iter.hasNext())
         {
             owner = iter.next();
-            fkValues = ord.getForeignKeyValues(owner,cld);
+            fkValues = getFkValuesForObject(owner);
             if (isNull(fkValues))
             {
                 continue;
@@ -154,6 +157,9 @@
      */
     protected Query buildPrefetchQuery(Collection ids)
     {
-        return buildPrefetchQuery(ids, getItemClassDescriptor().getPkFields());
+        ClassDescriptor cld = getItemClassDescriptor();       
+        FieldDescriptor fds[] = getObjectReferenceDescriptor().getForeignKeyTargetFieldDescriptors(cld);
+        
+        return buildPrefetchQuery(ids, fds);
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java Wed Feb 15 10:19:56 2006
@@ -15,9 +15,13 @@
  * limitations under the License.
  */
 
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PersistenceBrokerException;
 import org.apache.ojb.broker.core.PersistenceBrokerImpl;
+import org.apache.ojb.broker.core.ValueContainer;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
+import org.apache.ojb.broker.util.BrokerHelper;
 
 /**
  * Abstract Relationship Prefetchers.
@@ -104,4 +108,34 @@
     {
         this.cascadeRetrieve = cascadeRetrieve;
     }
+    
+    /**
+     * Get the values of the fk-target-fields for an obj.
+     * @param objOrProxy
+     * @throws PersistenceBrokerException
+     */
+    protected Object[] getFkTargetValuesForObject(Object objOrProxy) throws PersistenceBrokerException
+    {
+        PersistenceBroker pb = getBroker();
+        BrokerHelper helper = pb.serviceBrokerHelper();
+        ObjectReferenceDescriptor rds = getObjectReferenceDescriptor();
+        
+        ValueContainer[] values = helper.getFkTargetValuesForObject(rds, objOrProxy, false);
+        return helper.extractValueArray(values);
+    } 
+
+    /**
+     * Get the values of the fk-fields for an obj. 
+     * @param objOrProxy
+     * @throws PersistenceBrokerException
+     */
+    protected Object[] getFkValuesForObject(Object objOrProxy) throws PersistenceBrokerException
+    {
+        PersistenceBroker pb = getBroker();
+        BrokerHelper helper = pb.serviceBrokerHelper();
+        ObjectReferenceDescriptor rds = getObjectReferenceDescriptor();
+
+        ValueContainer[] values = helper.getFkValuesForObject(rds, objOrProxy, false);
+        return helper.extractValueArray(values);
+    } 
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java Wed Feb 15 10:19:56 2006
@@ -1120,7 +1120,7 @@
 
 				if (!cod.isMtoNRelation())
 				{
-					prevKeys = prev.cld.getPkFields();
+                    prevKeys = cod.getForeignKeyTargetFieldDescriptors(prev.cld);
 					keys = cod.getForeignKeyFieldDescriptors(cld);
 				}
 				else
@@ -1161,8 +1161,8 @@
 				    prev = ordAlias;
 				}	
 
-				prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
-				keys = cld.getPkFields();
+                prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
+                keys = ord.getForeignKeyTargetFieldDescriptors(cld);
 
 				// [olegnitz]
 				// a special case: the last element of the path is
@@ -1170,7 +1170,7 @@
 				// use the correspondent foreign key field, don't add the join
 				if ((fieldRef != null) && (i == (pathLength - 1)))
 				{
-					FieldDescriptor[] pk = cld.getPkFields();
+                    FieldDescriptor[] pk = ord.getForeignKeyTargetFieldDescriptors(cld);
 
 					for (int j = 0; j < pk.length; j++)
 					{
@@ -1777,9 +1777,10 @@
         {
             SuperReferenceDescriptor superRef = cld.getSuperReference();
             FieldDescriptor[] leftFields = superRef.getForeignKeyFieldDescriptors(cld);
+            FieldDescriptor[] rightFields = superRef.getForeignKeyTargetFieldDescriptors(superCld);
             
             TableAlias right = createTableAlias(superCld, null, name);
-            Join join1to1 = new Join(left, leftFields, right, superCld.getPkFields(), useOuterJoin, "superClass");
+            Join join1to1 = new Join(left, leftFields, right, rightFields, useOuterJoin, "superClass");
             left.addJoin(join1to1);
 
             buildSuperJoinTree(right, superCld, name, useOuterJoin);
@@ -1800,7 +1801,7 @@
             SuperReferenceDescriptor srd = subCld.getSuperReference();
             if (srd != null)
             {
-                FieldDescriptor[] leftFields = subCld.getPkFields();
+                FieldDescriptor[] leftFields = srd.getForeignKeyTargetFieldDescriptors(cld);
                 FieldDescriptor[] rightFields = srd.getForeignKeyFieldDescriptors(subCld);
 
                 TableAlias right = createTableAlias(subCld, null, name);

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- 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 Wed Feb 15 10:19:56 2006
@@ -1278,9 +1278,10 @@
         }
         else
         {
-            Class refClass = proxyFactory.getRealClass(referencedObject);
-            ClassDescriptor refCld = getClassDescriptor(refClass);
-            refPkValues = brokerHelper.getKeyValues(refCld, referencedObject, false);
+//            Class refClass = proxyFactory.getRealClass(referencedObject);
+//            ClassDescriptor refCld = getClassDescriptor(refClass);
+//            refPkValues = brokerHelper.getKeyValues(refCld, referencedObject, false);
+            refPkValues = brokerHelper.getFkTargetValuesForObject(rds, referencedObject, false);
         }
         for (int i = 0; i < objFkFields.length; i++)
         {

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java Wed Feb 15 10:19:56 2006
@@ -868,7 +868,7 @@
      */
     private QueryByCriteria getFKQueryMtoN(Object obj, ClassDescriptor cld, CollectionDescriptor cod)
     {
-        ValueContainer[] values = pb.serviceBrokerHelper().getKeyValues(cld, obj);
+        ValueContainer[] values = pb.serviceBrokerHelper().getFkTargetValuesForObject(cod, obj ,false);
         Object[] thisClassFks = cod.getFksToThisClass();
         Object[] itemClassFks = cod.getFksToItemClass();
         ClassDescriptor refCld = pb.getClassDescriptor(cod.getItemClass());
@@ -896,7 +896,7 @@
      */
     private QueryByCriteria getFKQuery1toN(Object obj, ClassDescriptor cld, CollectionDescriptor cod)
     {
-        ValueContainer[] container = pb.serviceBrokerHelper().getKeyValues(cld, obj);
+        ValueContainer[]  container = pb.serviceBrokerHelper().getFkTargetValuesForObject(cod, obj ,false);
         ClassDescriptor refCld = pb.getClassDescriptor(cod.getItemClass());
         FieldDescriptor[] fields = cod.getForeignKeyFieldDescriptors(refCld);
         Criteria criteria = new Criteria();

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java Wed Feb 15 10:19:56 2006
@@ -15,8 +15,12 @@
  * limitations under the License.
  */
 
-import java.util.Hashtable;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 import org.apache.commons.lang.builder.ToStringBuilder;
@@ -54,9 +58,14 @@
     private boolean m_OtmDependent = false;
 
     /**
-     * holds the foreign-key field descriptor array for a specified class
+     * holds the foreign-key field descriptor array for a specified class.
      */
-    private Hashtable fkFieldMap = new Hashtable();
+    private Map fkFieldMap = new HashMap();
+    /**
+     * holds the foreign-key target-field descriptor array for a specified class.
+     */
+    private Map fkTargetFieldMap = new HashMap();
+
     /**
      * define loading strategy of the resulting object
      */
@@ -89,7 +98,84 @@
     }
 
     /**
-     *
+     * Answer the FieldDescriptors for the Foreignkey-Target-Fields.
+     * These Fields are the Primarykey-Fields of the targetCld in most cases
+     * @param targetCld the classdescriptor to get the fields from
+     */
+    public FieldDescriptor[] getForeignKeyTargetFieldDescriptors(ClassDescriptor targetCld)
+    {
+        FieldDescriptor[] fkFieldDescriptors = (FieldDescriptor[]) fkTargetFieldMap.get(targetCld);
+        
+        if (fkFieldDescriptors == null)
+        {
+            List fkFields = getForeignKeyFields();
+            FieldDescriptor pkFields[] = targetCld.getPkFields();
+            
+            // get FieldDescriptor for each index from Class-descriptor
+            // In a many-to-many relationship Fk-Fields vector will be null.
+            if (fkFields != null)
+            {
+                if (targetCld.isInterface())
+                {
+                    //exchange interface class descriptor with first concrete class
+                    Vector extents = targetCld.getExtentClasses();
+                    // TODO: Check for side-effects
+                    Class firstConcreteClass = (Class) extents.get(0);
+                    targetCld = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
+                }
+                List ret = new ArrayList();
+
+                for (int i = 0; i < fkFields.size(); i++)
+                {
+                    ForeignKey fk = (ForeignKey) fkFields.get(i);
+                    FieldDescriptor fkfd;
+                    
+                    // if a target-field-ref is available use it
+                    if (fk.targetField != null)
+                    {
+                        fkfd = targetCld.getFieldDescriptorByName(fk.targetField);
+                        if (fkfd == null)
+                        {
+                            ClassDescriptor tmp = targetCld;
+                            while(tmp.getSuperClassDescriptor() != null)
+                            {
+                                fkfd = tmp.getFieldDescriptorByName((String) fk.fkField);
+                                if(fkfd != null)
+                                {
+                                    break;
+                                }
+                                else
+                                {
+                                    tmp = tmp.getSuperClassDescriptor();
+                                }
+                            }
+                        }
+                        if (fkfd == null)
+                        {
+                            throw new OJBRuntimeException("Incorrect or not found target-field reference name '"
+                                    + fk.targetField + "' in descriptor " + this + " for class-descriptor '"
+                                    + targetCld.getClassNameOfObject() + "'");
+                        }
+                    }
+                    // otherwise use the pks of the target class
+                    else
+                    {
+                        fkfd = pkFields[i];
+                    }
+                                      
+                    ret.add(fkfd);
+                }
+                
+                fkFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
+                fkTargetFieldMap.put(targetCld, fkFieldDescriptors);
+            }
+        }
+        return fkFieldDescriptors;
+    }
+
+    /**
+     * Answer the FieldDescriptors for the Foreignkey-Fields.
+     * @param cld the classdescriptor to get the fields from
      */
 	public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor cld)
 	{
@@ -105,8 +191,7 @@
 				Vector ret;
 				if (cld.isInterface())
 				{
-					//exchange interface class descriptor with first concrete
-					//class
+					//exchange interface class descriptor with first concrete class
 					Vector extents = cld.getExtentClasses();
 					Class firstConcreteClass = (Class) extents.get(0);
 					cld = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
@@ -116,7 +201,7 @@
 				Iterator iter = v.iterator();
 				while (iter.hasNext())
 				{
-					Object fk = iter.next();
+                    ForeignKey fk = (ForeignKey) iter.next();
 					FieldDescriptor fkfd = null;
 					/*
                     OJB-55
@@ -126,16 +211,16 @@
                     ClassDescriptor tmp = cld;
                     while(tmp != null)
                     {
-                        if (fk instanceof Integer)
+                        if (fk.fkField instanceof Integer)
                         {
-                            Integer index = (Integer) fk;
+                            Integer index = (Integer) fk.fkField;
                             fkfd = cld.getFieldDescriptorByIndex(index.intValue());
                         }
                         else
                         {
-                            fkfd = tmp.getFieldDescriptorByName((String) fk);
+                            fkfd = tmp.getFieldDescriptorByName((String) fk.fkField);
                         }
-                        if(fkfd != null)
+                        if (fkfd != null)
                         {
                             break;
                         }
@@ -148,7 +233,7 @@
                     if (fkfd == null)
 					{
                         throw new OJBRuntimeException("Incorrect or not found field reference name '"
-                                + fk + "' in descriptor " + this + " for class-descriptor '"
+                                + fk.fkField + "' in descriptor " + this + " for class-descriptor '"
                                 + (cld != null ? cld.getClassNameOfObject() + "'" : "'null'"));
 					}
 					ret.add(fkfd);
@@ -224,37 +309,55 @@
     }
 
     /**
-     *
+     * Sets the foreign keys.
+     * @param vec a Vector of Strings or Integers (the names or ids of the fields)
      */
     public void setForeignKeyFields(Vector vec)
     {
-        m_ForeignKeyFields = vec;
+        if (m_ForeignKeyFields != null)
+        {
+            m_ForeignKeyFields.clear();
+        }
+        Iterator iter = vec.iterator();
+        while (iter.hasNext())
+        {
+            addForeignKeyField(iter.next(), null);
+        }
     }
 
     /**
-     * add a foreign key field ID
+     * Add a foreign key field ID.
+     * @param fkId the id the foreign key field
      */
-    public void addForeignKeyField(int newId)
+    public void addForeignKeyField(int fkId)
     {
-        if (m_ForeignKeyFields == null)
-        {
-            m_ForeignKeyFields = new Vector();
-        }
-        m_ForeignKeyFields.add(new Integer(newId));
+        addForeignKeyField(new Integer(fkId), null);
     }
 
     /**
-     * add a foreign key field
+     * Add a foreign key field.
+     * @param fkField the id or name of the foreign key field
+     */
+    public void addForeignKeyField(String fkField)
+    {
+        addForeignKeyField(fkField, null);
+    }
+    
+    /**
+     * Add a foreign key field.
+     * @param fkField the id or name of the foreign key field
+     * @param targetField the name of the target field
      */
-    public void addForeignKeyField(String newField)
+    public void addForeignKeyField(Object fkField, String targetField)
     {
         if (m_ForeignKeyFields == null)
         {
             m_ForeignKeyFields = new Vector();
         }
-        m_ForeignKeyFields.add(newField);
+        m_ForeignKeyFields.add(new ForeignKey(fkField, targetField));
     }
 
+
     /**
      * Gets the refresh.
      * @return Returns a boolean
@@ -660,5 +763,22 @@
         result.append( tags.getClosingTagById( REFERENCE_DESCRIPTOR ) );
         result.append( eol );
         return result.toString();
+    }
+    
+    /**
+     * Helper to store the fkField and the field it's referencing.
+     */
+    static class ForeignKey implements Serializable
+    {
+        private static final long serialVersionUID = 3256718468362482741L;
+
+        Object fkField;
+        String targetField;
+
+        ForeignKey(Object fkField, String targetField)
+        {
+            this.fkField = fkField;
+            this.targetField = targetField;
+        }
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java Wed Feb 15 10:19:56 2006
@@ -112,6 +112,7 @@
     public static final int ID = 69;
     public static final int FIELD_ID_REF = 70;
     public static final int FIELD_REF = 84;
+    public static final int TARGET_FIELD_REF = 115;
     public static final int ATTRIBUTE = 71;
     public static final int ATTRIBUTE_NAME = 72;
     public static final int ATTRIBUTE_VALUE = 73;
@@ -143,7 +144,7 @@
     public static final int PROXY_PREFETCHING_LIMIT = 114;
 
     // maintain a next id to keep track where we are
-    static final int _NEXT = 115;
+    static final int _NEXT = 116;
 
     // String constants
     public static final String TAG_ACCESS = "access";
@@ -157,5 +158,4 @@
     public static final String CASCADE_NONE_STR = "none";
     public static final String CASCADE_LINK_STR = "link";
     public static final String CASCADE_OBJECT_STR = "object";
-
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java Wed Feb 15 10:19:56 2006
@@ -152,6 +152,7 @@
         table.put("id", new Integer(ID));
         table.put("field-id-ref", new Integer(FIELD_ID_REF));
         table.put("field-ref", new Integer(FIELD_REF));
+        table.put("target-field-ref", new Integer(TARGET_FIELD_REF));
         table.put("attribute", new Integer(ATTRIBUTE));
         table.put("attribute-name", new Integer(ATTRIBUTE_NAME));
         table.put("attribute-value", new Integer(ATTRIBUTE_VALUE));

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java Wed Feb 15 10:19:56 2006
@@ -571,38 +571,47 @@
 
                         break;
                     }
-
                 case FOREIGN_KEY:
                     {
-                        if (isDebug) logger.debug("    > " + tags.getTagById(FOREIGN_KEY));
-                        String fieldIdRef = atts.getValue(tags.getTagById(FIELD_ID_REF));
+                    if (isDebug)
+                        logger.debug("    > " + tags.getTagById(FOREIGN_KEY));
+                    String fieldIdRef = atts.getValue(tags.getTagById(FIELD_ID_REF));
 
-                        if (fieldIdRef != null)
-                        {
-                            if (isDebug) logger.debug("      " + tags.getTagById(FIELD_ID_REF) + ": " + fieldIdRef);
+                    if (fieldIdRef != null)
+                    {
+                        if (isDebug)
+                            logger.debug("      " + tags.getTagById(FIELD_ID_REF) + ": " + fieldIdRef);
 
-                            try
-                            {
-                                int fieldId;
-                                fieldId = Integer.parseInt(fieldIdRef);
-                                m_CurrentORD.addForeignKeyField(fieldId);
-                            }
-                            catch (NumberFormatException rex)
-                            {
-                                throw new MetadataException(tags.getTagById(FIELD_ID_REF)
-                                        + " attribute must be an int. Found: "
-                                        + fieldIdRef + ". Please check your repository file.", rex);
-                            }
+                        try
+                        {
+                            int fieldId;
+                            fieldId = Integer.parseInt(fieldIdRef);
+                            m_CurrentORD.addForeignKeyField(fieldId);
                         }
-                        else
+                        catch (NumberFormatException rex)
                         {
-                            String fieldRef = atts.getValue(tags.getTagById(FIELD_REF));
-                            if (isDebug) logger.debug("      " + tags.getTagById(FIELD_REF) + ": " + fieldRef);
-                            m_CurrentORD.addForeignKeyField(fieldRef);
+                            throw new MetadataException(tags.getTagById(FIELD_ID_REF)
+                                    + " attribute must be an int. Found: " + fieldIdRef
+                                    + ". Please check your repository file.", rex);
                         }
-                        break;
                     }
+                    else
+                    {
+                        String fieldRef = atts.getValue(tags.getTagById(FIELD_REF));
+                        String targetFieldRef = atts.getValue(tags.getTagById(TARGET_FIELD_REF));
 
+                        if (isDebug)
+                        {
+                            logger.debug("      " + tags.getTagById(FIELD_REF) + ": " + fieldRef);
+                            if (targetFieldRef != null)
+                            {
+                                logger.debug("      " + tags.getTagById(TARGET_FIELD_REF) + ": " + targetFieldRef);
+                            }
+                        }
+                        m_CurrentORD.addForeignKeyField(fieldRef, targetFieldRef);
+                    }
+                    break;
+                }
                 case COLLECTION_DESCRIPTOR:
                     {
                         if (isDebug) logger.debug("    > " + tags.getTagById(COLLECTION_DESCRIPTOR));
@@ -716,34 +725,45 @@
                     }
                 case INVERSE_FK:
                     {
-                        if (isDebug) logger.debug("    > " + tags.getTagById(INVERSE_FK));
-                        String fieldIdRef = atts.getValue(tags.getTagById(FIELD_ID_REF));
+                    if (isDebug)
+                        logger.debug("    > " + tags.getTagById(INVERSE_FK));
+                    String fieldIdRef = atts.getValue(tags.getTagById(FIELD_ID_REF));
+
+                    if (fieldIdRef != null)
+                    {
+                        if (isDebug)
+                            logger.debug("      " + tags.getTagById(FIELD_ID_REF) + ": " + fieldIdRef);
 
-                        if (fieldIdRef != null)
+                        try
+                        {
+                            int fieldId;
+                            fieldId = Integer.parseInt(fieldIdRef);
+                            m_CurrentCOD.addForeignKeyField(fieldId);
+                        }
+                        catch (NumberFormatException rex)
                         {
-                            if (isDebug) logger.debug("      " + tags.getTagById(FIELD_ID_REF) + ": " + fieldIdRef);
+                            throw new MetadataException(tags.getTagById(FIELD_ID_REF)
+                                    + " attribute must be an int. Found: " + fieldIdRef
+                                    + " Please check your repository file.", rex);
+                        }
+                    }
+                    else
+                    {
+                        String fieldRef = atts.getValue(tags.getTagById(FIELD_REF));
+                        String targetFieldRef = atts.getValue(tags.getTagById(TARGET_FIELD_REF));
 
-                            try
-                            {
-                                int fieldId;
-                                fieldId = Integer.parseInt(fieldIdRef);
-                                m_CurrentCOD.addForeignKeyField(fieldId);
-                            }
-                            catch (NumberFormatException rex)
+                        if (isDebug)
+                        {
+                            logger.debug("      " + tags.getTagById(FIELD_REF) + ": " + fieldRef);
+                            if (targetFieldRef != null)
                             {
-                                throw new MetadataException(tags.getTagById(FIELD_ID_REF)
-                                        + " attribute must be an int. Found: "
-                                        + fieldIdRef + " Please check your repository file.", rex);
+                                logger.debug("      " + tags.getTagById(TARGET_FIELD_REF) + ": " + targetFieldRef);
                             }
                         }
-                        else
-                        {
-                            String fieldRef = atts.getValue(tags.getTagById(FIELD_REF));
-                            if (isDebug) logger.debug("      " + tags.getTagById(FIELD_REF) + ": " + fieldRef);
-                            m_CurrentCOD.addForeignKeyField(fieldRef);
-                        }
-                        break;
+                        m_CurrentCOD.addForeignKeyField(fieldRef, targetFieldRef);
                     }
+                    break;
+                }
 
                 case FK_POINTING_TO_THIS_CLASS:
                     {

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/BrokerHelper.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/BrokerHelper.java?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/BrokerHelper.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/BrokerHelper.java Wed Feb 15 10:19:56 2006
@@ -19,6 +19,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -178,6 +179,54 @@
             return getValuesForObject(realCld.getPkFields(), objectOrProxy, convertToSql);
         }
     }
+
+    /**
+     * Get the values of the fk-target-fields for an obj.
+     * @param rds
+     * @param objOrProxy
+     * @throws PersistenceBrokerException
+     */
+    public ValueContainer[] getFkTargetValuesForObject(ObjectReferenceDescriptor rds, Object objOrProxy, boolean convertToSql) throws PersistenceBrokerException
+    {
+        Class refClass = m_broker.getProxyFactory().getRealClass(objOrProxy);
+        ClassDescriptor refCld = m_broker.getClassDescriptor(refClass);
+        FieldDescriptor pkFd[] = refCld.getPkFields();
+        FieldDescriptor targetFd[] = rds.getForeignKeyTargetFieldDescriptors(refCld);
+
+        // use the values of the key-fields
+        if (targetFd.length == 0 || Arrays.equals(pkFd, targetFd))
+        {
+            return getKeyValues(refCld, objOrProxy, convertToSql);
+        }
+        
+        // use the values of the target-fields
+        Object obj = m_broker.getProxyFactory().getRealObject(objOrProxy);
+        return getValuesForObject(targetFd, obj, convertToSql);
+    } 
+
+    /**
+     * Get the values of the fk-fields for an obj.
+     * @param rds
+     * @param objOrProxy
+     * @throws PersistenceBrokerException
+     */
+    public ValueContainer[] getFkValuesForObject(ObjectReferenceDescriptor rds, Object objOrProxy, boolean convertToSql) throws PersistenceBrokerException
+    {
+        Class refClass = m_broker.getProxyFactory().getRealClass(objOrProxy);
+        ClassDescriptor refCld = m_broker.getClassDescriptor(refClass);
+        FieldDescriptor pkFd[] = refCld.getPkFields();
+        FieldDescriptor targetFd[] = rds.getForeignKeyFieldDescriptors(refCld);
+
+        // use the values of the key-fields
+        if (targetFd.length == 0 || Arrays.equals(pkFd, targetFd))
+        {
+            return getKeyValues(refCld, objOrProxy, convertToSql);
+        }
+
+        // use the values of the target-fields
+        Object obj = m_broker.getProxyFactory().getRealObject(objOrProxy);
+        return getValuesForObject(targetFd, obj, convertToSql);
+    } 
 
     /**
      * Return primary key values of given Identity object.

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/schema/ojbtest-schema.xml
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/schema/ojbtest-schema.xml?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/schema/ojbtest-schema.xml (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/schema/ojbtest-schema.xml Wed Feb 15 10:19:56 2006
@@ -1151,7 +1151,7 @@
             <reference local="FK_PRO_ID" foreign="PRO_ID"/>
         </foreign-key>
     </table>
-    
+
     <table name="COL_2_SUB_PROJECT_SELF">
         <column name="SUB_ID" required="true" primaryKey="true" type="INTEGER"/>
         <column name="NAME" type="VARCHAR" size="150"/>
@@ -1762,4 +1762,166 @@
         <column name="NAME" type="VARCHAR" size="250"/>
     </table>
 
+    <table name="CALLS">
+        <column name="CALLS_ID"
+                javaName="callsId"
+                type="INTEGER"
+                primaryKey="true"
+                required="true"
+        />
+        <column name="PHONE_NUMBER_ID"
+                javaName="phoneNumberId"
+                type="INTEGER"
+        />
+        <column name="CALL_DATE"
+                javaName="callDate"
+                type="DATE"
+        />
+        <column name="CALL_TIME"
+                javaName="callTime"
+                type="TIME"
+        />
+        <column name="NUMBER_CALLED"
+                javaName="numberCalled"
+                type="VARCHAR"
+                size="250"
+        />
+        <foreign-key foreignTable="PHONE_NUMBER">
+            <reference local="PHONE_NUMBER_ID" foreign="PHONE_NUMBER_ID"/>
+        </foreign-key>
+    </table>
+    <table name="OJB_HL_SEQ">
+        <column name="TABLENAME"
+                javaName="tableName"
+                type="VARCHAR"
+                primaryKey="true"
+                required="true"
+                size="250"
+        />
+        <column name="FIELDNAME"
+                javaName="fieldName"
+                type="VARCHAR"
+                primaryKey="true"
+                required="true"
+                size="250"
+        />
+        <column name="MAX_KEY"
+                javaName="maxKey"
+                type="BIGINT"
+        />
+        <column name="GRAB_SIZE"
+                javaName="grabSize"
+                type="INTEGER"
+        />
+        <column name="VERSION"
+                javaName="version"
+                type="INTEGER"
+        />
+    </table>
+    <table name="PHONE_NUMBER">
+        <column name="PHONE_NUMBER_ID"
+                javaName="phoneNumberId"
+                type="INTEGER"
+                primaryKey="true"
+                required="true"
+        />
+        <column name="RF_TELKO_ID"
+                javaName="rftelcoId"
+                type="INTEGER"
+        />
+        <column name="NUMBER"
+                javaName="number"
+                type="VARCHAR"
+                size="250"
+        />
+        <foreign-key foreignTable="RFTELCO">
+            <reference local="RF_TELKO_ID" foreign="RF_TELKO_ID"/>
+        </foreign-key>
+    </table>
+    <table name="RFTELCO">
+        <column name="RF_TELKO_ID"
+                javaName="rftelcoId"
+                type="INTEGER"
+                primaryKey="true"
+                required="true"
+        />
+        <column name="PARTNER_ID_USER"
+                javaName="partnerIdUser"
+                type="VARCHAR"
+                size="250"
+        />
+        <column name="FIRST_NAME"
+                javaName="firstName"
+                type="VARCHAR"
+                size="250"
+        />
+        <column name="LAST_NAME"
+                javaName="lastName"
+                type="VARCHAR"
+                size="250"
+        />
+        <column name="NAME_SUFFIX"
+                javaName="nameSuffix"
+                type="VARCHAR"
+                size="250"
+        />
+        <column name="STREET"
+                javaName="street"
+                type="VARCHAR"
+                size="250"
+        />
+        <column name="ZIP"
+                javaName="zip"
+                type="VARCHAR"
+                size="250"
+        />
+        <column name="CITY"
+                javaName="city"
+                type="VARCHAR"
+                size="250"
+        />
+    </table>
+    
+  <!-- Tables with references using non-pk-field -->
+  <table name="Kategorien_2"
+         	javaName="ProductGroup_2">
+    <column name="Kategorie_Nr" required="true" primaryKey="true" type="INTEGER"
+            javaName="groupId"/>
+    <column name="Kategorie_Name" type="VARCHAR" size="150"
+            javaName="groupName"/>
+    <column name="Beschreibung" type="VARCHAR" size="150"
+            javaName="description"/>
+	<unique name="Unique_Name">
+		<unique-column name="Kategorie_Name"/>
+    </unique>
+  </table>
+
+  <table name="Artikel_2"
+         	javaName="Article_2">
+    <column name="Artikel_Nr" required="true" primaryKey="true" type="INTEGER"
+            javaName="articleId"/>
+    <column name="Artikelname" type="VARCHAR" size="150"
+            javaName="articleName"/>
+    <column name="Lieferanten_Nr" type="INTEGER"
+            javaName="supplierId"/>
+    <column name="KatName" type="VARCHAR" size="150"
+            javaName="productGroupName"/>
+    <column name="Liefereinheit" type="VARCHAR" size="150"
+            javaName="unit"/>
+    <column name="Einzelpreis" type="FLOAT"
+            javaName="price"/>
+    <column name="Lagerbestand" type="INTEGER"
+            javaName="stock"/>
+    <column name="BestellteEinheiten" type="INTEGER"
+            javaName="orderedUnits"/>
+    <column name="MindestBestand" type="INTEGER"
+            javaName="minimumStock"/>
+    <column name="Auslaufartikel" type="INTEGER"
+            javaName="inSelloutArticle"/>
+    <foreign-key foreignTable="Kategorien_2">
+      	<reference local="KatName" foreign="Kategorie_Name"/>
+    </foreign-key>
+  </table>
+  
+  
 </database>

Added: db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/NoPkReferenceTest.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/NoPkReferenceTest.java?rev=378046&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/NoPkReferenceTest.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/NoPkReferenceTest.java Wed Feb 15 10:19:56 2006
@@ -0,0 +1,230 @@
+package org.apache.ojb.broker;
+
+/* Copyright 2002-2004 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.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.ojb.broker.query.Criteria;
+import org.apache.ojb.broker.query.Query;
+import org.apache.ojb.broker.query.QueryFactory;
+import org.apache.ojb.junit.PBTestCase;
+
+/**
+ * Test for relationships based on non-pk-attributes
+ *
+ * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
+ * @version $Id: NoPkReferenceTest.java 364433 2005-01-06 21:00:06Z brj $
+ */
+public class NoPkReferenceTest extends PBTestCase
+{
+
+    public static void main(String[] args)
+    {
+        String[] arr = {NoPkReferenceTest.class.getName()};
+        junit.textui.TestRunner.main(arr);
+    }
+    
+    private ProductGroup_2 createProductGroup(String groupName)
+    {
+        ProductGroup_2 pg;
+        Article_2 a1;
+        Article_2 a2;
+        List articles = new ArrayList();
+        
+        pg = new ProductGroup_2(groupName, "This is Group " + groupName);
+        a1 = new Article_2("Art-" + groupName + "-1");
+        a2 = new Article_2("Art-" + groupName + "-2");
+
+        a1.setProductGroup(pg);
+        a2.setProductGroup(pg);
+        articles.add(a1);
+        articles.add(a2);
+        pg.setAllArticlesInGroup(articles);
+
+        return pg;
+    }
+    
+    /**
+     * Insert a ProductGroup with 2 Articles
+     */
+    public void testInsert()
+    {
+        Criteria crit;
+        Query q;
+        Collection result;
+        Iterator iter;
+        Identity pgIdentity;
+
+        String name = "Grp-NoPkReferenceTest" + System.currentTimeMillis();
+        ProductGroup_2 pg = createProductGroup(name);
+        Article_2 article;
+        
+        broker.beginTransaction();
+        broker.store(pg);        
+        broker.commitTransaction();
+        pgIdentity = broker.serviceIdentity().buildIdentity(pg);
+        
+        broker.clearCache();      
+        
+        // check existence of ProductGroup
+        pg = (ProductGroup_2) broker.getObjectByIdentity(pgIdentity);
+        assertNotNull(pg);
+        assertEquals(name, pg.getGroupName());
+        assertEquals(2, pg.getAllArticlesInGroup().size());
+        
+        broker.clearCache();
+
+        // check existence of Articles
+        crit = new Criteria();
+        crit.addEqualTo("productGroupName", name);
+        q = QueryFactory.newQuery(Article_2.class, crit);
+        result = broker.getCollectionByQuery(q);
+        assertEquals(2, result.size());
+
+        iter = result.iterator();
+        while (iter.hasNext())
+        {
+            article = (Article_2) iter.next();
+            assertEquals(name, article.getProductGroup().getName());
+        }
+        
+    }
+
+    public void testQueryNoJoin()
+    {
+        Criteria crit;
+        Query q;
+        Collection result;
+        Iterator iter;
+
+        String name = "Grp-NoPkReferenceTest" + System.currentTimeMillis();
+        ProductGroup_2 pg = createProductGroup(name);
+        Article_2 article;
+        
+        broker.beginTransaction();
+        broker.store(pg);        
+        broker.commitTransaction();
+        
+        broker.clearCache();       
+        
+        // look for Articles using attribute of ProductGroup
+        // no join required because groupName is the target for the fk
+        crit = new Criteria();
+        crit.addEqualTo("productGroup.groupName", name);
+        q = QueryFactory.newQuery(Article_2.class, crit);
+        result = broker.getCollectionByQuery(q);
+        assertEquals(2, result.size());
+
+        iter = result.iterator();
+        while (iter.hasNext())
+        {
+            article = (Article_2) iter.next();
+            assertEquals(name, article.getProductGroup().getName());
+        }
+    }
+
+    public void testQueryJoin()
+    {
+        Criteria crit;
+        Query q;
+        Collection result;
+        Iterator iter;
+        Integer pgId;
+
+        String name = "Grp-NoPkReferenceTest" + System.currentTimeMillis();
+        ProductGroup_2 pg = createProductGroup(name);
+        Article_2 article;
+        
+        broker.beginTransaction();
+        broker.store(pg);        
+        broker.commitTransaction();
+        pgId = pg.getGroupId();
+        
+        broker.clearCache();       
+        
+        // look for Articles using attribute of ProductGroup 
+        // join is required 
+        crit = new Criteria();
+        crit.addEqualTo("productGroup.groupId", pgId);
+        q = QueryFactory.newQuery(Article_2.class, crit);
+        result = broker.getCollectionByQuery(q);
+        assertEquals(2, result.size());
+
+        iter = result.iterator();
+        while (iter.hasNext())
+        {
+            article = (Article_2) iter.next();
+            assertEquals(name, article.getProductGroup().getName());
+        }
+    }
+
+    //
+    // Testclasses ----------------------------------------------
+    //
+    public static class ProductGroup_2 extends ProductGroup
+    {
+        public ProductGroup_2()
+        {
+            super();
+        }
+
+        /**
+         * @param pGroupId
+         * @param pGroupName
+         * @param pDescription
+         */
+        public ProductGroup_2(String pGroupName, String pDescription)
+        {
+            super(null, pGroupName, pDescription);
+        }
+}
+    
+    public static class Article_2 extends Article
+    {
+        private String productGroupName;
+        
+        public Article_2()
+        {
+            super();
+        }
+
+        public Article_2(String articleName)
+        {
+            super();
+            setArticleId(null);
+            setArticleName(articleName);
+        }
+        
+        /**
+         * @return Returns the groupName.
+         */
+        
+        public String getProductGroupName()
+        {
+            return productGroupName;
+        }
+        /**
+         * @param groupName The groupName to set.
+         */
+        public void setProductGroupName(String groupName)
+        {
+            this.productGroupName = groupName;
+        }
+    }
+}

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository.dtd
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository.dtd?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository.dtd (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository.dtd Wed Feb 15 10:19:56 2006
@@ -720,6 +720,7 @@
 <!ATTLIST foreignkey
 	field-id-ref CDATA #IMPLIED
 	field-ref CDATA #IMPLIED
+	target-field-ref CDATA #IMPLIED  
 >
 
 
@@ -853,6 +854,7 @@
 <!ATTLIST inverse-foreignkey
 	field-id-ref CDATA #IMPLIED
 	field-ref CDATA #IMPLIED
+	target-field-ref CDATA #IMPLIED  
 >
 
 <!--
@@ -1029,4 +1031,4 @@
 	(documentation?, attribute*)>
 <!ATTLIST constant-argument
     value CDATA #REQUIRED
->
+>
\ No newline at end of file

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository_junit.xml
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository_junit.xml?rev=378046&r1=378045&r2=378046&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository_junit.xml (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/repository_junit.xml Wed Feb 15 10:19:56 2006
@@ -2899,6 +2899,107 @@
          <foreignkey field-ref="productGroupId"/>
       </reference-descriptor>
    </class-descriptor>
+   
+   <!-- Test classes using non-pk-fields for relationships-->
+
+   <class-descriptor
+   	  class="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
+   	  table="Artikel_2"
+   >
+      <field-descriptor
+         name="articleId"
+         column="Artikel_Nr"
+         jdbc-type="INTEGER"
+         primarykey="true"
+         autoincrement="true"
+      />
+      <field-descriptor
+         name="articleName"
+         column="Artikelname"
+         jdbc-type="VARCHAR"
+      />
+      <field-descriptor
+         name="supplierId"
+         column="Lieferanten_Nr"
+         jdbc-type="INTEGER"
+      />
+      <field-descriptor
+         name="productGroupName"
+         column="KatName"
+         jdbc-type="VARCHAR"
+      />
+      <field-descriptor
+         name="unit"
+         column="Liefereinheit"
+         jdbc-type="VARCHAR"
+      />
+      <field-descriptor
+         name="price"
+         column="Einzelpreis"
+         jdbc-type="FLOAT"
+      />
+      <field-descriptor
+         name="stock"
+         column="Lagerbestand"
+         jdbc-type="INTEGER"
+      />
+      <field-descriptor
+         name="orderedUnits"
+         column="BestellteEinheiten"
+         jdbc-type="INTEGER"
+      />
+      <field-descriptor
+         name="minimumStock"
+         column="MindestBestand"
+         jdbc-type="INTEGER"
+      />
+      <field-descriptor
+         name="isSelloutArticle"
+         column="Auslaufartikel"
+         jdbc-type="INTEGER"
+         conversion="org.apache.ojb.broker.accesslayer.conversions.Boolean2IntFieldConversion"
+      >
+      </field-descriptor>
+
+      <reference-descriptor
+            name="productGroup"
+            class-ref="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
+      >
+         <foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
+      </reference-descriptor>
+   </class-descriptor>
+
+   <class-descriptor
+   	  class="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
+   	  table="Kategorien_2"
+   >
+      <field-descriptor
+         name="groupId"
+         column="Kategorie_Nr"
+         jdbc-type="INTEGER"
+         primarykey="true"
+         autoincrement="true"
+      />
+      <field-descriptor
+         name="groupName"
+         column="Kategorie_Name"
+         jdbc-type="VARCHAR"
+      />
+      <field-descriptor
+         name="description"
+         column="Beschreibung"
+         jdbc-type="VARCHAR"
+      />
+      <collection-descriptor
+         name="allArticlesInGroup"
+         element-class-ref="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
+         auto-retrieve="true"
+         auto-update="true"
+         auto-delete="false"
+      >
+         <inverse-foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
+      </collection-descriptor>
+   </class-descriptor>
 
     <!-- ************************************************* -->
     <!-- Class to Test Field type            			   -->



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