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 2005/01/06 22:00:06 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql TableAliasHandler.java
brj 2005/01/06 13:00:06
Modified: src/schema ojbtest-schema.xml
src/java/org/apache/ojb/broker/core
PersistenceBrokerImpl.java
QueryReferenceBroker.java
src/java/org/apache/ojb/broker/accesslayer
CollectionPrefetcher.java ReferencePrefetcher.java
RelationshipPrefetcherImpl.java
src/test/org/apache/ojb repository_junit.xml repository.dtd
src/java/org/apache/ojb/broker/metadata
CollectionDescriptor.java RepositoryTags.java
RepositoryElements.java
DiscriminatorFieldDescriptor.java
RepositoryXmlHandler.java
ObjectReferenceDescriptor.java
src/java/org/apache/ojb/broker/util BrokerHelper.java
. release-notes.txt
src/java/org/apache/ojb/broker/accesslayer/sql
TableAliasHandler.java
Added: src/test/org/apache/ojb/broker NoPkReferenceTest.java
Log:
new feature to support non-pk-fields as target-fields in 1:1 and 1:n relationships
Revision Changes Path
1.1 db-ojb/src/test/org/apache/ojb/broker/NoPkReferenceTest.java
Index: NoPkReferenceTest.java
===================================================================
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,v 1.1 2005/01/06 21:00:00 brj Exp $
*/
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;
}
}
}
1.91 +42 -1 db-ojb/src/schema/ojbtest-schema.xml
Index: ojbtest-schema.xml
===================================================================
RCS file: /home/cvs/db-ojb/src/schema/ojbtest-schema.xml,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -r1.90 -r1.91
--- ojbtest-schema.xml 18 Dec 2004 19:28:47 -0000 1.90
+++ ojbtest-schema.xml 6 Jan 2005 21:00:00 -0000 1.91
@@ -1537,6 +1537,47 @@
<!-- ************ Object Factory tests * END -->
+ <!-- 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"
+ 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>
1.108 +2 -4 db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
Index: PersistenceBrokerImpl.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java,v
retrieving revision 1.107
retrieving revision 1.108
diff -u -r1.107 -r1.108
--- PersistenceBrokerImpl.java 26 Dec 2004 20:57:30 -0000 1.107
+++ PersistenceBrokerImpl.java 6 Jan 2005 21:00:00 -0000 1.108
@@ -1237,9 +1237,7 @@
}
else
{
- Class refClass = ProxyHelper.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++)
{
1.28 +25 -19 db-ojb/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java
Index: QueryReferenceBroker.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- QueryReferenceBroker.java 10 Dec 2004 22:40:42 -0000 1.27
+++ QueryReferenceBroker.java 6 Jan 2005 21:00:00 -0000 1.28
@@ -48,6 +48,7 @@
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.QueryFactory;
+import org.apache.ojb.broker.util.BrokerHelper;
import org.apache.ojb.broker.util.collections.ManageableListImpl;
import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
import org.apache.ojb.broker.util.logging.Logger;
@@ -110,7 +111,7 @@
// now iterate over all elements and add them to the new collection
iter = pb.getIteratorFromQuery(query, cld);
- // BRJ : get fullSizefor Query
+ // BRJ : get fullSize for Query
// to be removed when Query.fullSize is removed
if (iter instanceof PagingIterator)
{
@@ -442,7 +443,10 @@
*/
private Identity getReferencedObjectIdentity(Object obj, ObjectReferenceDescriptor rds, ClassDescriptor cld)
{
- Object[] fkValues = rds.getForeignKeyValues(obj, cld);
+ BrokerHelper helper = pb.serviceBrokerHelper();
+ FieldDescriptor[] fds = rds.getForeignKeyFieldDescriptors(cld);
+ Object[] fkValues = helper.extractValueArray(helper.getValuesForObject(fds, obj, false));
+
FieldDescriptor[] fkFieldDescriptors = rds.getForeignKeyFieldDescriptors(cld);
boolean hasNullifiedFKValue = hasNullifiedFK(fkFieldDescriptors, fkValues);
/*
@@ -641,12 +645,12 @@
/**
* Answer the foreign key query to retrieve the collection
- * defined by CollectionDescriptor
+ * defined by CollectionDescriptor.
*
- * @param obj
- * @param cld
- * @param cds
- * @return
+ * @param obj the owner of the relationship
+ * @param cld the ClassDescriptor for the owner
+ * @param cod the CollectionDescriptor
+ * @return org.apache.ojb.broker.query.Query
*/
private Query getFKQuery(Object obj, ClassDescriptor cld, CollectionDescriptor cds)
{
@@ -685,17 +689,18 @@
return fkQuery;
}
- /**
- * Get Foreign key query for m:n <br>
- * supports UNIDIRECTIONAL m:n using QueryByMtoNCriteria
- * @return org.apache.ojb.broker.query.QueryByCriteria
+ /**
+ * Get Foreign key query for m:n relationship <br>
+ * supports UNIDIRECTIONAL m:n using QueryByMtoNCriteria.
+ *
* @param obj the owner of the relationship
* @param cld the ClassDescriptor for the owner
* @param cod the CollectionDescriptor
+ * @return org.apache.ojb.broker.query.QueryByCriteria
*/
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 = cod.getItemClassDescriptor();
@@ -716,15 +721,16 @@
}
/**
- * Get Foreign key query for 1:n
+ * Get Foreign key query for 1:n relationship.
+ *
+ * @param obj the owner of the relationship
+ * @param cld the ClassDescriptor for the owner
+ * @param cod the CollectionDescriptor
* @return org.apache.ojb.broker.query.QueryByCriteria
- * @param obj
- * @param cld
- * @param cod
*/
private QueryByCriteria getFKQuery1toN(Object obj, ClassDescriptor cld, CollectionDescriptor cod)
{
- ValueContainer[] container = pb.serviceBrokerHelper().getKeyValues(cld, obj);
+ ValueContainer[] values = pb.serviceBrokerHelper().getFkTargetValuesForObject(cod, obj ,false);
ClassDescriptor refCld = cod.getItemClassDescriptor();
FieldDescriptor[] fields = cod.getForeignKeyFieldDescriptors(refCld);
Criteria criteria = new Criteria();
@@ -732,7 +738,7 @@
for (int i = 0; i < fields.length; i++)
{
FieldDescriptor fld = fields[i];
- criteria.addEqualTo(fld.getAttributeName(), container[i].getValue());
+ criteria.addEqualTo(fld.getAttributeName(), values[i].getValue());
}
return QueryFactory.newQuery(refCld.getClassOfObject(), criteria);
1.34 +9 -9 db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java
Index: CollectionPrefetcher.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- CollectionPrefetcher.java 5 Dec 2004 12:31:01 -0000 1.33
+++ CollectionPrefetcher.java 6 Jan 2005 21:00:00 -0000 1.34
@@ -74,7 +74,6 @@
IdentityFactory idFactory = pb.serviceIdentity();
ClassDescriptor cld = getOwnerClassDescriptor();
Class topLevelClass = pb.getTopLevelClass(cld.getClassOfObject());
- BrokerHelper helper = pb.serviceBrokerHelper();
Collection queries = new ArrayList(owners.size());
Collection idsSubset = new HashSet(owners.size());
Object[] fkValues;
@@ -85,7 +84,8 @@
while (iter.hasNext())
{
owner = iter.next();
- fkValues = helper.extractValueArray(helper.getKeyValues(cld, owner));
+ fkValues = getFkTargetValuesForObject(owner);
+
id = idFactory.buildIdentity(null, topLevelClass, fkValues);
idsSubset.add(id);
if (idsSubset.size() == pkLimit)
@@ -156,17 +156,16 @@
for (Iterator it = owners.iterator(); it.hasNext();)
{
Object owner = it.next();
- ownerIdsToLists.put(new Identity(owner, pb), new ArrayList());
+ Object[] targetValues = getFkTargetValuesForObject(owner);
+ Identity ownerId = idFactory.buildIdentity(null, ownerTopLevelClass, targetValues);
+ ownerIdsToLists.put(ownerId, new ArrayList());
}
// build the children lists for the owners
for (Iterator it = children.iterator(); it.hasNext();)
{
Object child = it.next();
- // 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 = idFactory.buildIdentity(null, ownerTopLevelClass, fkValues);
List list = (List) ownerIdsToLists.get(ownerId);
@@ -181,7 +180,8 @@
{
Object result;
Object owner = it.next();
- Identity ownerId = new Identity(owner, pb);
+ Object[] targetValues = getFkTargetValuesForObject(owner);
+ Identity ownerId = idFactory.buildIdentity(null, ownerTopLevelClass, targetValues);
List list = (List) ownerIdsToLists.get(ownerId);
if ((collectionClass == null) && field.getType().isArray())
1.23 +24 -16 db-ojb/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java
Index: ReferencePrefetcher.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- ReferencePrefetcher.java 14 Sep 2004 16:03:33 -0000 1.22
+++ ReferencePrefetcher.java 6 Jan 2005 21:00:00 -0000 1.23
@@ -22,14 +22,17 @@
import java.util.Iterator;
import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.IdentityFactory;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.cache.LocalCache;
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;
+
/**
* Relationship Prefetcher for References.
*
@@ -56,34 +59,32 @@
protected void associateBatched(Collection owners, Collection children)
{
ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
- ClassDescriptor cld = getOwnerClassDescriptor();
- Object owner;
- Object relatedObject;
- Object fkValues[];
- Identity id;
PersistenceBroker pb = getBroker();
PersistentField field = ord.getPersistentField();
Class topLevelClass = pb.getTopLevelClass(ord.getItemClass());
HashMap childrenMap = new HashMap(children.size());
+ IdentityFactory idFactory = pb.serviceIdentity();
for (Iterator it = children.iterator(); it.hasNext(); )
{
- relatedObject = it.next();
- childrenMap.put(new Identity(relatedObject, pb), relatedObject);
+ Object relatedObject = it.next();
+ Object[] targetValues = getFkTargetValuesForObject(relatedObject);
+ Identity id = idFactory.buildIdentity(null, topLevelClass, targetValues);
+ childrenMap.put(id, relatedObject);
}
for (Iterator it = owners.iterator(); it.hasNext(); )
{
- owner = it.next();
- fkValues = ord.getForeignKeyValues(owner,cld);
+ Object owner = it.next();
+ Object[] fkValues = getFkValuesForObject(owner);
if (isNull(fkValues))
{
field.set(owner, null);
continue;
}
- id = new Identity(null, topLevelClass, fkValues);
- relatedObject = childrenMap.get(id);
+ Identity id = idFactory.buildIdentity(null, topLevelClass, fkValues);
+ Object relatedObject = childrenMap.get(id);
field.set(owner, relatedObject);
}
}
@@ -107,7 +108,6 @@
*/
protected Query[] buildPrefetchQueries(Collection owners, Collection children)
{
- ClassDescriptor cld = getOwnerClassDescriptor();
ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
Collection queries = new ArrayList(owners.size());
Collection idsSubset = new HashSet(owners.size());
@@ -118,16 +118,18 @@
Identity id;
PersistenceBrokerImpl pb = getBroker();
LocalCache cache = pb.ojbLocalCache();
+ IdentityFactory idFactory = pb.serviceIdentity();
while (iter.hasNext())
{
owner = iter.next();
- fkValues = ord.getForeignKeyValues(owner,cld);
+ fkValues = getFkValuesForObject(owner);
+
if (isNull(fkValues))
{
continue;
}
- id = new Identity(null, topLevelClass, fkValues);
+ id = idFactory.buildIdentity(null, topLevelClass, fkValues);
if (cache.lookup(id) != null)
{
children.add(pb.getObjectByIdentity(id));
@@ -154,6 +156,12 @@
*/
protected Query buildPrefetchQuery(Collection ids)
{
- return buildPrefetchQuery(ids, getItemClassDescriptor().getPkFields());
+ ClassDescriptor cld = getItemClassDescriptor();
+ FieldDescriptor fds[];
+
+// fds = cld.getPkFields();
+ fds = getObjectReferenceDescriptor().getForeignKeyTargetFieldDescriptors(cld);
+
+ return buildPrefetchQuery(ids, fds);
}
}
1.15 +38 -2 db-ojb/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java
Index: RelationshipPrefetcherImpl.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- RelationshipPrefetcherImpl.java 10 Dec 2004 22:40:42 -0000 1.14
+++ RelationshipPrefetcherImpl.java 6 Jan 2005 21:00:00 -0000 1.15
@@ -15,10 +15,14 @@
* 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.
* Each Prefetcher handles a single Relationship (1:1 or 1:n)
@@ -104,4 +108,36 @@
{
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);
+ }
+
}
1.129 +105 -4 db-ojb/src/test/org/apache/ojb/repository_junit.xml
Index: repository_junit.xml
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/repository_junit.xml,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -r1.128 -r1.129
--- repository_junit.xml 18 Dec 2004 14:01:18 -0000 1.128
+++ repository_junit.xml 6 Jan 2005 21:00:01 -0000 1.129
@@ -153,7 +153,7 @@
>
<orderby name="articleId" sort="DESC"/>
- <inverse-foreignkey field-ref="productGroupId"/>
+ <inverse-foreignkey field-ref="productGroupId" target-field-ref="groupId"/>
</collection-descriptor>
</class-descriptor>
@@ -1529,7 +1529,7 @@
name="productGroup"
class-ref="org.apache.ojb.broker.ProductGroup"
>
- <foreignkey field-ref="productGroupId"/>
+ <foreignkey field-ref="productGroupId" target-field-ref="groupId"/>
</reference-descriptor>
</class-descriptor>
@@ -3717,11 +3717,112 @@
name="productGroup"
class-ref="org.apache.ojb.broker.ProductGroup"
auto-retrieve="true"
- auto-update="true"
+ auto-update="true"
>
<documentation>this is the reference to an articles productgroup</documentation>
<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>
<!-- Mapping of classes used in junit tests and tutorials ends here -->
1.60 +2 -0 db-ojb/src/test/org/apache/ojb/repository.dtd
Index: repository.dtd
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/repository.dtd,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- repository.dtd 14 Sep 2004 16:51:04 -0000 1.59
+++ repository.dtd 6 Jan 2005 21:00:01 -0000 1.60
@@ -608,6 +608,7 @@
<!ATTLIST foreignkey
field-id-ref CDATA #IMPLIED
field-ref CDATA #IMPLIED
+ target-field-ref CDATA #IMPLIED
>
@@ -740,6 +741,7 @@
<!ATTLIST inverse-foreignkey
field-id-ref CDATA #IMPLIED
field-ref CDATA #IMPLIED
+ target-field-ref CDATA #IMPLIED
>
<!--
1.33 +96 -40 db-ojb/src/java/org/apache/ojb/broker/metadata/CollectionDescriptor.java
Index: CollectionDescriptor.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/CollectionDescriptor.java,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- CollectionDescriptor.java 10 Dec 2004 22:40:42 -0000 1.32
+++ CollectionDescriptor.java 6 Jan 2005 21:00:02 -0000 1.33
@@ -204,77 +204,122 @@
public String toXML()
{
String eol = SystemUtils.LINE_SEPARATOR;
+ StringBuffer result = new StringBuffer(1024);
// write opening tag
- String result = " " + RepositoryTags.getOpeningTagNonClosingById(COLLECTION_DESCRIPTOR) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(COLLECTION_DESCRIPTOR));
+ result.append(eol);
// write attributes
// name
- result += " " + RepositoryTags.getAttribute(FIELD_NAME,this.getAttributeName()) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(FIELD_NAME, getAttributeName()));
+ result.append(eol);
// collection class is optional
if (getCollectionClassName() != null)
{
- result += " " + RepositoryTags.getAttribute(COLLECTION_CLASS,this.getCollectionClassName()) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(COLLECTION_CLASS, getCollectionClassName()));
+ result.append(eol);
}
// element-class-ref
- result += " " + RepositoryTags.getAttribute(ITEMS_CLASS,this.getItemClassName()) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(ITEMS_CLASS, getItemClassName()));
+ result.append(eol);
// indirection-table is optional
if (isMtoNRelation())
{
- result += " " + RepositoryTags.getAttribute(INDIRECTION_TABLE,getIndirectionTable()) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(INDIRECTION_TABLE, getIndirectionTable()));
+ result.append(eol);
}
// proxyReference is optional, disabled by default
if (isLazy())
{
- result += " " + RepositoryTags.getAttribute(PROXY_REFERENCE,"true") + eol;
- result += " " + RepositoryTags.getAttribute(PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit()) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(PROXY_REFERENCE, "true"));
+ result.append(eol);
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(PROXY_PREFETCHING_LIMIT, String
+ .valueOf(getProxyPrefetchingLimit())));
+ result.append(eol);
}
//reference refresh is optional, disabled by default
if (isRefresh())
{
- result += " " + RepositoryTags.getAttribute(REFRESH,"true") + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(REFRESH, "true"));
+ result.append(eol);
}
//auto retrieve
- result += " " + RepositoryTags.getAttribute(AUTO_RETRIEVE, "" + getCascadeRetrieve()) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(AUTO_RETRIEVE, String.valueOf(getCascadeRetrieve())));
+ result.append(eol);
//auto update
- result += " " + RepositoryTags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())));
+ result.append(eol);
//auto delete
- result += " " + RepositoryTags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())) + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())));
+ result.append(eol);
//otm-dependent is optional, disabled by default
if (getOtmDependent())
{
- result += " " + RepositoryTags.getAttribute(OTM_DEPENDENT, "true") + eol;
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(OTM_DEPENDENT, "true"));
+ result.append(eol);
}
// close opening tag
- result += " >" + eol;
+ result.append(" >");
+ result.append(eol);
// write elements
- // inverse fk elements
- for (int i=0;i<getForeignKeyFields().size();i++)
- {
- Object obj = getForeignKeyFields().get(i);
- if (obj instanceof Integer)
+ // inverse fk elements
+ for (int i = 0; i < getForeignKeyFields().size(); i++)
{
+ ForeignKey obj = (ForeignKey) getForeignKeyFields().get(i);
+ if (obj.fkField instanceof Integer)
+ {
String fkId = obj.toString();
- result += " " + RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK) + " ";
- result += RepositoryTags.getAttribute(FIELD_ID_REF, fkId) + "/>" + eol;
- }
- else
- {
- String fk = (String) obj;
- result += " " + RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK) + " ";
- result += RepositoryTags.getAttribute(FIELD_REF, fk) + "/>" + eol;
- }
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK));
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(FIELD_ID_REF, fkId));
+ if (obj.targetField != null)
+ {
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
+ }
+ result.append("/>");
+ result.append(eol);
+ }
+ else
+ {
+ String fk = (String) obj.fkField;
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK));
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(FIELD_REF, fk));
+ if (obj.targetField != null)
+ {
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
+ }
+ result.append("/>");
+ result.append(eol);
+ }
}
// write optional M:N elements
@@ -282,25 +327,36 @@
if (isMtoNRelation())
{
// foreign keys to this class
- for (int i=0;i<getFksToThisClass().length;i++)
- {
+ for (int i = 0; i < getFksToThisClass().length; i++)
+ {
String fkId = getFksToThisClass()[i];
- result += " " + RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_THIS_CLASS) + " ";
- result += RepositoryTags.getAttribute(COLUMN_NAME, fkId) + "/>" + eol;
- }
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_THIS_CLASS));
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(COLUMN_NAME, fkId));
+ result.append("/>");
+ result.append(eol);
+ }
// foreign keys to item class
- for (int i=0;i<getFksToItemClass().length;i++)
- {
+ for (int i = 0; i < getFksToItemClass().length; i++)
+ {
String fkId = getFksToItemClass()[i];
- result += " " + RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_ITEMS_CLASS) + " ";
- result += RepositoryTags.getAttribute(COLUMN_NAME, fkId) + "/>" + eol;
- }
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_ITEMS_CLASS));
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(COLUMN_NAME, fkId));
+ result.append("/>");
+ result.append(eol);
+ }
}
// closing tag
- result += " " + RepositoryTags.getClosingTagById(COLLECTION_DESCRIPTOR) + eol;
- return result;
+ result.append(" ");
+ result.append(RepositoryTags.getClosingTagById(COLLECTION_DESCRIPTOR));
+ result.append(eol);
+
+ return result.toString();
}
/**
1.40 +1 -0 db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java
Index: RepositoryTags.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- RepositoryTags.java 26 Oct 2004 15:27:40 -0000 1.39
+++ RepositoryTags.java 6 Jan 2005 21:00:02 -0000 1.40
@@ -147,6 +147,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));
1.40 +2 -1 db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java
Index: RepositoryElements.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- RepositoryElements.java 26 Oct 2004 15:27:40 -0000 1.39
+++ RepositoryElements.java 6 Jan 2005 21:00:02 -0000 1.40
@@ -110,6 +110,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 = 122;
public static final int ATTRIBUTE = 71;
public static final int ATTRIBUTE_NAME = 72;
public static final int ATTRIBUTE_VALUE = 73;
@@ -148,7 +149,7 @@
public static final int USE_OBJECT_FACTORY = 121;
// maintain a next id to keep track where we are
- static final int _NEXT = 120;
+ static final int _NEXT = 123;
// String constants
public static final String TAG_ACCESS = "access";
1.2 +5 -1 db-ojb/src/java/org/apache/ojb/broker/metadata/DiscriminatorFieldDescriptor.java
Index: DiscriminatorFieldDescriptor.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/DiscriminatorFieldDescriptor.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DiscriminatorFieldDescriptor.java 15 Aug 2004 12:42:28 -0000 1.1
+++ DiscriminatorFieldDescriptor.java 6 Jan 2005 21:00:02 -0000 1.2
@@ -39,6 +39,8 @@
*/
public class DiscriminatorFieldDescriptor extends FieldDescriptor
{
+ private static final long serialVersionUID = 3978989851393995062L;
+
private String m_value;
/**
@@ -150,6 +152,8 @@
*/
private class DiscriminatorPersistentField implements PersistentField
{
+ private static final long serialVersionUID = 4051328942017689655L;
+
/**
* Return the value of the discriminator.
* @param ignoreObj the object is not used
1.67 +23 -5 db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java
Index: RepositoryXmlHandler.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -r1.66 -r1.67
--- RepositoryXmlHandler.java 14 Nov 2004 09:36:10 -0000 1.66
+++ RepositoryXmlHandler.java 6 Jan 2005 21:00:02 -0000 1.67
@@ -623,8 +623,17 @@
else
{
String fieldRef = atts.getValue(RepositoryTags.getTagById(FIELD_REF));
- if (isDebug) logger.debug(" " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
- m_CurrentORD.addForeignKeyField(fieldRef);
+ String targetFieldRef = atts.getValue(RepositoryTags.getTagById(TARGET_FIELD_REF));
+
+ if (isDebug)
+ {
+ logger.debug(" " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
+ if (targetFieldRef != null)
+ {
+ logger.debug(" " + RepositoryTags.getTagById(TARGET_FIELD_REF) + ": " + targetFieldRef);
+ }
+ }
+ m_CurrentORD.addForeignKeyField(fieldRef, targetFieldRef);
}
break;
}
@@ -765,8 +774,17 @@
else
{
String fieldRef = atts.getValue(RepositoryTags.getTagById(FIELD_REF));
- if (isDebug) logger.debug(" " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
- m_CurrentCOD.addForeignKeyField(fieldRef);
+ String targetFieldRef = atts.getValue(RepositoryTags.getTagById(TARGET_FIELD_REF));
+
+ if (isDebug)
+ {
+ logger.debug(" " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
+ if (targetFieldRef != null)
+ {
+ logger.debug(" " + RepositoryTags.getTagById(TARGET_FIELD_REF) + ": " + targetFieldRef);
+ }
+ }
+ m_CurrentCOD.addForeignKeyField(fieldRef, targetFieldRef);
}
break;
}
1.42 +253 -158 db-ojb/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java
Index: ObjectReferenceDescriptor.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- ObjectReferenceDescriptor.java 10 Dec 2004 22:40:41 -0000 1.41
+++ ObjectReferenceDescriptor.java 6 Jan 2005 21:00:02 -0000 1.42
@@ -15,8 +15,11 @@
* limitations under the License.
*/
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Vector;
import org.apache.commons.lang.builder.ToStringBuilder;
@@ -56,9 +59,14 @@
private boolean multiMappedClass = 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 m_fkFieldMap = new HashMap();
+ /**
+ * holds the foreign-key target-field descriptor array for a specified class.
+ */
+ private Map m_fkTargetFieldMap = new HashMap();
+
/**
* define loading strategy of the resulting object
*/
@@ -89,88 +97,124 @@
}
return m_ProxyOfItems;
}
-
+
/**
- *
+ * Answer the FieldDescriptors for the Foreignkey-Fields.
+ * @param cld the classdescriptor to get the fields from
*/
- public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor mif)
- {
- FieldDescriptor[] foreignKeyFieldDescriptors = null;
- if ((foreignKeyFieldDescriptors = (FieldDescriptor[]) fkFieldMap.get(mif)) == null)
- {
- // 1. collect vector of indices of Fk-Fields
- Vector v = getForeignKeyFields();
- // 2. get FieldDescriptor for each index from Class-descriptor
- // 2A. In a many-to-many relationship foreignkeyfields vector will be null.
- if (v != null)
- {
- Vector ret;
- if (mif.isInterface())
- {
- //exchange interface class descriptor with first concrete
- //class
- Vector extents = mif.getExtentClasses();
+ public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor cld)
+ {
+ FieldDescriptor[] fkFieldDescriptors = (FieldDescriptor[]) m_fkFieldMap.get(cld);
+
+ if (fkFieldDescriptors == null)
+ {
+ List fkFields = getForeignKeyFields();
+
+ // get FieldDescriptor for each index from Class-descriptor
+ // In a many-to-many relationship Fk-Fields vector will be null.
+ if (fkFields != null)
+ {
+ if (cld.isInterface())
+ {
+ //exchange interface class descriptor with first concrete class
+ Vector extents = cld.getExtentClasses();
// TODO: Check for side-effects
- Class firstConcreteClass = (Class) extents.get(0);
- mif = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
- }
- ret = new Vector();
-
- Iterator iter = v.iterator();
- while (iter.hasNext())
- {
- Object fk = iter.next();
- FieldDescriptor fkfd;
- if (fk instanceof Integer)
- {
- Integer index = (Integer) fk;
- fkfd = mif.getFieldDescriptorByIndex(index.intValue());
- }
- else
- {
- fkfd = mif.getFieldDescriptorByName((String) fk);
- }
- if (fkfd == null)
- {
- throw new OJBRuntimeException("Incorrect or not found field reference name '"
- + fk + "' in descriptor " + this + " for class-descriptor '"
- + mif.getClassNameOfObject() + "'");
- }
- ret.add(fkfd);
- }
- foreignKeyFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
- fkFieldMap.put(mif, foreignKeyFieldDescriptors);
- }
- }
- return foreignKeyFieldDescriptors;
- }
-
- /**
- * @throws MetadataException if an error occours while accessing ForeingKey values on obj
- */
- public Object[] getForeignKeyValues(Object obj, ClassDescriptor mif)
- throws PersistenceBrokerException
- {
- FieldDescriptor[] fks = getForeignKeyFieldDescriptors(mif);
- Object[] result = new Object[fks.length];
- for (int i = 0; i < result.length; i++)
- {
- FieldDescriptor fmd = fks[i];
- PersistentField f = fmd.getPersistentField();
-
- // BRJ: do NOT convert.
- // conversion is done when binding the sql-statement
- //
- // FieldConversion fc = fmd.getFieldConversion();
- // Object val = fc.javaToSql(f.get(obj));
-
- Object val = f.get(obj);
- result[i] = val;
+ Class firstConcreteClass = (Class) extents.get(0);
+ cld = 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 (fk.fkField instanceof Integer)
+ {
+ Integer index = (Integer) fk.fkField;
+ fkfd = cld.getFieldDescriptorByIndex(index.intValue());
+ }
+ else
+ {
+ fkfd = cld.getFieldDescriptorByName((String) fk.fkField);
+ }
+ if (fkfd == null)
+ {
+ throw new OJBRuntimeException("Incorrect or not found field reference name '"
+ + fk.fkField + "' in descriptor " + this + " for class-descriptor '"
+ + cld.getClassNameOfObject() + "'");
+ }
+
+ ret.add(fkfd);
+ }
+
+ fkFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
+ m_fkFieldMap.put(cld, fkFieldDescriptors);
+ }
}
- return result;
+ return fkFieldDescriptors;
}
/**
+ * 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[]) m_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)
+ {
+ 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()]);
+ m_fkTargetFieldMap.put(targetCld, fkFieldDescriptors);
+ }
+ }
+ return fkFieldDescriptors;
+ }
+
+ /**
* Answer the ItemClass.
*/
public Class getItemClass()
@@ -226,25 +270,29 @@
/**
* add a foreign key field ID
*/
- 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
*/
- public void addForeignKeyField(String newField)
+ public void addForeignKeyField(String fkField)
+ {
+ addForeignKeyField(fkField, null);
+ }
+
+ /**
+ * add a foreign key field
+ */
+ 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));
}
/**
@@ -389,15 +437,15 @@
protected int getCascadeStoreValue(String cascade)
{
- if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_NONE_STR))
+ if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_NONE_STR))
{
return CASCADE_NONE;
}
- else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_LINK_STR))
+ else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_LINK_STR))
{
return CASCADE_LINK;
}
- else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_OBJECT_STR))
+ else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_OBJECT_STR))
{
return CASCADE_OBJECT;
}
@@ -417,23 +465,23 @@
else
{
throw new OJBRuntimeException("Invalid value! Given value was '" + cascade
- + "', expected values are: " + RepositoryTags.CASCADE_NONE_STR + ", "
- + RepositoryTags.CASCADE_LINK_STR + ", " + RepositoryTags.CASCADE_OBJECT_STR
+ + "', expected values are: " + RepositoryElements.CASCADE_NONE_STR + ", "
+ + RepositoryElements.CASCADE_LINK_STR + ", " + RepositoryElements.CASCADE_OBJECT_STR
+ " ('false' and 'true' are deprecated but still valid)");
}
}
protected int getCascadeDeleteValue(String cascade)
{
- if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_NONE_STR))
+ if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_NONE_STR))
{
return CASCADE_NONE;
}
- else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_LINK_STR))
+ else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_LINK_STR))
{
return CASCADE_LINK;
}
- else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_OBJECT_STR))
+ else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_OBJECT_STR))
{
return CASCADE_OBJECT;
}
@@ -448,8 +496,8 @@
else
{
throw new OJBRuntimeException("Invalid value! Given value was '" + cascade
- + "', expected values are: " + RepositoryTags.CASCADE_NONE_STR + ", "
- + RepositoryTags.CASCADE_LINK_STR + ", " + RepositoryTags.CASCADE_OBJECT_STR
+ + "', expected values are: " + RepositoryElements.CASCADE_NONE_STR + ", "
+ + RepositoryElements.CASCADE_LINK_STR + ", " + RepositoryElements.CASCADE_OBJECT_STR
+ " ('false' and 'true' are deprecated but still valid)");
}
}
@@ -460,13 +508,13 @@
switch(cascade)
{
case CASCADE_NONE:
- result = RepositoryTags.CASCADE_NONE_STR;
+ result = RepositoryElements.CASCADE_NONE_STR;
break;
case CASCADE_LINK:
- result = RepositoryTags.CASCADE_LINK_STR;
+ result = RepositoryElements.CASCADE_LINK_STR;
break;
case CASCADE_OBJECT:
- result = RepositoryTags.CASCADE_OBJECT_STR;
+ result = RepositoryElements.CASCADE_OBJECT_STR;
break;
}
return result;
@@ -511,7 +559,7 @@
public void setPersistentField(PersistentField field)
{
super.setPersistentField(field);
- if ((field.getName() != null) && field.getName().equals(RepositoryTags.TAG_SUPER))
+ if ((field.getName() != null) && field.getName().equals(RepositoryElements.TAG_SUPER))
{
setMultiMappedClass(true);
}
@@ -538,107 +586,154 @@
*/
public String toXML()
{
- String eol = System.getProperty( "line.separator" );
+ String eol = System.getProperty("line.separator");
// opening tag
- StringBuffer result = new StringBuffer( 1024 );
- result.append( " " );
- result.append( RepositoryTags.getOpeningTagNonClosingById( REFERENCE_DESCRIPTOR ) );
- result.append( eol );
+ StringBuffer result = new StringBuffer(1024);
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(REFERENCE_DESCRIPTOR));
+ result.append(eol);
// attributes
// name
String name = this.getAttributeName();
- if( name == null )
+ if (name == null)
{
name = RepositoryElements.TAG_SUPER;
}
- result.append( " " );
- result.append( RepositoryTags.getAttribute( FIELD_NAME, name ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(FIELD_NAME, name));
+ result.append(eol);
// class-ref
- result.append( " " );
- result.append( RepositoryTags.getAttribute( REFERENCED_CLASS, this.getItemClassName() ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(REFERENCED_CLASS, getItemClassName()));
+ result.append(eol);
// proxyReference is optional
- if( isLazy() )
+ if (isLazy())
{
- result.append( " " );
- result.append( RepositoryTags.getAttribute( PROXY_REFERENCE, "true" ) );
- result.append( eol );
- result.append( " " );
- result.append( RepositoryTags.getAttribute( PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit() ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(PROXY_REFERENCE, "true"));
+ result.append(eol);
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(PROXY_PREFETCHING_LIMIT, String
+ .valueOf(getProxyPrefetchingLimit())));
+ result.append(eol);
}
//reference refresh is optional, disabled by default
- if( isRefresh() )
+ if (isRefresh())
{
- result.append( " " );
- result.append( RepositoryTags.getAttribute( REFRESH, "true" ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(REFRESH, "true"));
+ result.append(eol);
}
//auto retrieve
- result.append( " " );
- result.append( RepositoryTags.getAttribute( AUTO_RETRIEVE, "" + getCascadeRetrieve() ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(AUTO_RETRIEVE, String.valueOf(getCascadeRetrieve())));
+ result.append(eol);
//auto update
- result.append( " " );
- result.append( RepositoryTags.getAttribute( AUTO_UPDATE, getCascadeAsString( getCascadingStore() ) ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())));
+ result.append(eol);
//auto delete
- result.append( " " );
- result.append( RepositoryTags.getAttribute( AUTO_DELETE, getCascadeAsString( getCascadingDelete() ) ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())));
+ result.append(eol);
//otm-dependent is optional, disabled by default
- if( getOtmDependent() )
+ if (getOtmDependent())
{
- result.append( " " );
- result.append( RepositoryTags.getAttribute( OTM_DEPENDENT, "true" ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(OTM_DEPENDENT, "true"));
+ result.append(eol);
}
// close opening tag
- result.append( " >" );
- result.append( eol );
+ result.append(" >");
+ result.append(eol);
// elements
// write foreignkey elements
- for( int i = 0; i < getForeignKeyFields().size(); i++ )
+ for (int i = 0; i < getForeignKeyFields().size(); i++)
{
- Object obj = getForeignKeyFields().get( i );
- if( obj instanceof Integer )
+ ForeignKey obj = (ForeignKey) getForeignKeyFields().get(i);
+ if (obj.fkField instanceof Integer)
{
String fkId = obj.toString();
- result.append( " " );
- result.append( RepositoryTags.getOpeningTagNonClosingById( FOREIGN_KEY ) );
- result.append( " " );
- result.append( RepositoryTags.getAttribute( FIELD_ID_REF, fkId ) );
- result.append( "/>" );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(FOREIGN_KEY));
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(FIELD_ID_REF, fkId));
+ if (obj.targetField != null)
+ {
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
+ }
+ result.append("/>");
+ result.append(eol);
}
else
{
- String fk = ( String ) obj;
- result.append( " " );
- result.append( RepositoryTags.getOpeningTagNonClosingById( FOREIGN_KEY ) );
- result.append( " " );
- result.append( RepositoryTags.getAttribute( FIELD_REF, fk ) );
- result.append( "/>" );
- result.append( eol );
+ String fk = (String) obj.fkField;
+ result.append(" ");
+ result.append(RepositoryTags.getOpeningTagNonClosingById(FOREIGN_KEY));
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(FIELD_REF, fk));
+ if (obj.targetField != null)
+ {
+ result.append(" ");
+ result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
+ }
+ result.append("/>");
+ result.append(eol);
}
}
// closing tag
- result.append( " " );
- result.append( RepositoryTags.getClosingTagById( REFERENCE_DESCRIPTOR ) );
- result.append( eol );
+ result.append(" ");
+ result.append(RepositoryTags.getClosingTagById(REFERENCE_DESCRIPTOR));
+ result.append(eol);
+
return result.toString();
}
+
+ /**
+ * Helper to store the fkField and the field it's referencing.
+ */
+ protected 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;
+ }
+ }
+
+ /**
+ * Helper to store the FieldDescriptor for the fkField and the field it's referencing.
+ */
+ protected static class FkFieldDescriptor implements Serializable
+ {
+ private static final long serialVersionUID = 3689348819137475895L;
+
+ FieldDescriptor fkField;
+ FieldDescriptor targetField;
+
+ FkFieldDescriptor(FieldDescriptor fkField, FieldDescriptor targetField)
+ {
+ this.fkField = fkField;
+ this.targetField = targetField;
+ }
+ }
+
}
1.75 +56 -3 db-ojb/src/java/org/apache/ojb/broker/util/BrokerHelper.java
Index: BrokerHelper.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/util/BrokerHelper.java,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -r1.74 -r1.75
--- BrokerHelper.java 13 Dec 2004 19:49:12 -0000 1.74
+++ BrokerHelper.java 6 Jan 2005 21:00:03 -0000 1.75
@@ -16,6 +16,7 @@
*/
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -329,15 +330,67 @@
}
/**
+ * 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 = ProxyHelper.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
+ else
+ {
+ Object obj = ProxyHelper.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 = ProxyHelper.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
+ else
+ {
+ Object obj = ProxyHelper.getRealObject(objOrProxy);
+ return getValuesForObject(targetFd, obj, convertToSql);
+ }
+ }
+
+ /**
* Get the values of the fields for an obj
* @param fields
- * @param obj
+ * @param objOrProxy
* @throws PersistenceBrokerException
*/
public ValueContainer[] getValuesForObject(FieldDescriptor[] fields, Object obj, boolean convertToSql) throws PersistenceBrokerException
{
ValueContainer[] result = new ValueContainer[fields.length];
-
+
for(int i = 0; i < fields.length; i++)
{
FieldDescriptor fd = fields[i];
1.75 +62 -1 db-ojb/release-notes.txt
Index: release-notes.txt
===================================================================
RCS file: /home/cvs/db-ojb/release-notes.txt,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -r1.74 -r1.75
--- release-notes.txt 18 Dec 2004 14:14:04 -0000 1.74
+++ release-notes.txt 6 Jan 2005 21:00:04 -0000 1.75
@@ -17,6 +17,67 @@
New ant-target ojb-quickstart creates archives of ready-to-run apps for tutorials 1 and 2
complete with pre-created Hsqldb databases (based on ojb-blank).
These archives are also available in the binary download area.
+- 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:
--
1.7 +7 -7 db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/TableAliasHandler.java
Index: TableAliasHandler.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/TableAliasHandler.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TableAliasHandler.java 2 Dec 2004 21:37:46 -0000 1.6
+++ TableAliasHandler.java 6 Jan 2005 21:00:06 -0000 1.7
@@ -344,7 +344,7 @@
if (!cod.isMtoNRelation())
{
- prevKeys = prev.cld.getPkFields();
+ prevKeys = cod.getForeignKeyTargetFieldDescriptors(prev.cld);
keys = cod.getForeignKeyFieldDescriptors(cld);
}
else
@@ -380,7 +380,7 @@
}
prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
- keys = cld.getPkFields();
+ keys = ord.getForeignKeyTargetFieldDescriptors(cld);
// [olegnitz]
// a special case: the last element of the path is
@@ -388,7 +388,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++)
{
@@ -695,11 +695,11 @@
while (objRefs.hasNext())
{
ObjectReferenceDescriptor objRef = (ObjectReferenceDescriptor) objRefs.next();
- FieldDescriptor[] leftFields = objRef.getForeignKeyFieldDescriptors(cld);
-
- ClassDescriptor refCld = cld.getRepository().getDescriptorFor(objRef.getItemClassName());
+
if (objRef.getPersistentField() instanceof AnonymousPersistentFieldForInheritance)
{
+ FieldDescriptor[] leftFields = objRef.getForeignKeyFieldDescriptors(cld);
+ ClassDescriptor refCld = cld.getRepository().getDescriptorFor(objRef.getItemClassName());
TableAlias base_alias = getTableAliasForPath(name, null);
String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++;
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org