You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-user@db.apache.org by ol...@ppi.de on 2004/09/03 13:08:00 UTC

non-equal Identities for primary-key fields with FieldConversion

Hello,

I am currently porting our application from OJB 1.0.0rc4 to OJB 1.0.0

A new problem has been introduced since then in
MtoNCollectionPrefetcher.associateBatched,
as Jakob points out in this source's javadoc:

BRJ: There is a potential problem with the type of the pks used to build the
Identities.
 * When creating an Identity for the owner, the type of pk is defined by the
instvars 
 * representing the pk. When creating the Identity based on the
mToNImplementor the
 * type of the pk is defined by the jdbc-type of field-descriptor of the
referenced class.
 * This type mismatch results in Identities not being equal. <br>
 * Integer[] {10,20,30} is not equal Long[] {10,20,30}

In my application, I use primary keys of type Long mapped to BigDecimal.
The issue then results in the stacktrace below.

java.lang.NullPointerException
 at
org.apache.ojb.broker.accesslayer.MtoNCollectionPrefetcher.associateBatched(
MtoNCollectionPrefetcher.java:408)
 at
org.apache.ojb.broker.accesslayer.MtoNCollectionPrefetcher.prefetchRelations
hip(MtoNCollectionPrefetcher.java:94)
 at
org.apache.ojb.broker.core.QueryReferenceBroker$PBPrefetchingListener.prefet
ch(QueryReferenceBroker.java:873)
 at
org.apache.ojb.broker.core.QueryReferenceBroker$PBCollectionProxyListener.be
foreLoading(QueryReferenceBroker.java:930)
 at
org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.beforeLoading(Co
llectionProxyDefaultImpl.java:182)
 at
org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.getData(Collecti
onProxyDefaultImpl.java:425)
 at
org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.toArray(Collecti
onProxyDefaultImpl.java:260)
 at
de.ppi.neuwerk.repman.persistent.ojb.AuditOjb.getCreatedNodes(AuditOjb.java:
157)

With some effort, I tried also current CVS head, and the problem is still
there.

Any ideas for a workaround?  I wonder if anybody else has this problem?!
I cannot image that we are the only ones who have primary-key fields with
FieldConversion
and who use m:n-Collections.

Best regards,
  Olli

P.S. I am committer myself, and I apologize for my long absence from active
participation.



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


Re: non-equal Identities for primary-key fields with FieldConversion

Posted by Jakob Braeuchi <jb...@gmx.ch>.
hi oli, ludovic,

could you please post the part of the repository that causes the problem ?

as i mentioned in  http://nagoya.apache.org/scarab/issues/id/OJB296 it's not 
sufficient to use the field-conversion of only one class. imo the conversion 
should be done on both fk-sets:

....
Object[] mToN = (Object[]) it.next();
System.arraycopy(mToN, 0, ownerPk, 0, ownerPkLen);
System.arraycopy(mToN, ownerPkLen, childPk, 0, childPkLen);

ownerPk = convert_keys(ownerPk, ownerCld);
childPk = convert_keys(childPk, childCld);

Identity ownerId = idFactory.buildIdentity(null, ownerTopLevelClass, ownerPk);
Identity childId = idFactory.buildIdentity(null, childTopLevelClass, childPk);
....

what do you think about ?

jakob

Ludovic Maitre (POP - Factory Part) schrieb:

> hello,
> 
> I have the same problem and use the following patch. Tell me if this 
> help (and if this is safe!):
> [line added are precede by LMA]
>    protected void associateBatched(Collection owners, Collection 
> children, Collection mToNImplementors)
>    {
>        CollectionDescriptor cds = getCollectionDescriptor();
>        PersistentField field = cds.getPersistentField();
>        //LMA: Use a field conversion if necessary
>        //[Solve the potential problem described above]
>        FieldConversion fc = 
> cds.getClassDescriptor().getPrimaryKey().getFieldConversion();
>        PersistenceBroker pb = getBroker();
>        Class ownerTopLevelClass = 
> pb.getTopLevelClass(getOwnerClassDescriptor().getClassOfObject());
>        Class childTopLevelClass = 
> pb.getTopLevelClass(getItemClassDescriptor().getClassOfObject());
>        Class collectionClass = cds.getCollectionClass(); // this 
> collection type will be used:
>        HashMap childMap = new HashMap();
>        HashMap ownerIdsToLists = new HashMap();
> 
>        // initialize the owner list map
>        for (Iterator it = owners.iterator(); it.hasNext();)
>        {
>            Object owner = it.next();
>            ownerIdsToLists.put(new Identity(owner, pb), new ArrayList());
>        }
> 
>        // build the children map
>        for (Iterator it = children.iterator(); it.hasNext();)
>        {
>            Object child = it.next();
>            childMap.put(new Identity(child, pb), child);
>        }
> 
>        int ownerPkLen = getOwnerClassDescriptor().getPkFields().length;
>        int childPkLen = getItemClassDescriptor().getPkFields().length;
>        Object[] ownerPk = new Object[ownerPkLen];
>        Object[] childPk = new Object[childPkLen];
> 
>        // build list of children based on m:n implementors
>        for (Iterator it = mToNImplementors.iterator(); it.hasNext();)
>        {
>            Object[] mToN = (Object[]) it.next();
>            //LMA: Use the field conversion if it exist. We assume that 
> the pk of the 2 objects are of the same type.
>            //[solve the potential problem described by BRJ]
>            if (fc!=null)
>                    for (int i=0;i<mToN.length;i++)
>                        mToN[i]=fc.sqlToJava(mToN[i]);
>            System.arraycopy(mToN, 0, ownerPk, 0, ownerPkLen);
>            System.arraycopy(mToN, ownerPkLen, childPk, 0, childPkLen);
> 
>            Identity ownerId = new Identity(null, ownerTopLevelClass, 
> ownerPk);
>            Identity childId = new Identity(null, childTopLevelClass, 
> childPk);
> 
>            // Identities may not be equal due to type-mismatch
>            Collection list = (Collection) ownerIdsToLists.get(ownerId);
>            Object child = childMap.get(childId);
>            list.add(child);
>        }
> 
> oliver.matz@ppi.de wrote:
> 
>> Hello,
>>
>> I am currently porting our application from OJB 1.0.0rc4 to OJB 1.0.0
>>
>> A new problem has been introduced since then in
>> MtoNCollectionPrefetcher.associateBatched,
>> as Jakob points out in this source's javadoc:
>>
>> BRJ: There is a potential problem with the type of the pks used to 
>> build the
>> Identities.
>> * When creating an Identity for the owner, the type of pk is defined 
>> by the
>> instvars * representing the pk. When creating the Identity based on the
>> mToNImplementor the
>> * type of the pk is defined by the jdbc-type of field-descriptor of the
>> referenced class.
>> * This type mismatch results in Identities not being equal. <br>
>> * Integer[] {10,20,30} is not equal Long[] {10,20,30}
>>
>> In my application, I use primary keys of type Long mapped to BigDecimal.
>> The issue then results in the stacktrace below.
>>
>> java.lang.NullPointerException
>> at
>> org.apache.ojb.broker.accesslayer.MtoNCollectionPrefetcher.associateBatched( 
>>
>> MtoNCollectionPrefetcher.java:408)
>> at
>> org.apache.ojb.broker.accesslayer.MtoNCollectionPrefetcher.prefetchRelations 
>>
>> hip(MtoNCollectionPrefetcher.java:94)
>> at
>> org.apache.ojb.broker.core.QueryReferenceBroker$PBPrefetchingListener.prefet 
>>
>> ch(QueryReferenceBroker.java:873)
>> at
>> org.apache.ojb.broker.core.QueryReferenceBroker$PBCollectionProxyListener.be 
>>
>> foreLoading(QueryReferenceBroker.java:930)
>> at
>> org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.beforeLoading(Co 
>>
>> llectionProxyDefaultImpl.java:182)
>> at
>> org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.getData(Collecti 
>>
>> onProxyDefaultImpl.java:425)
>> at
>> org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.toArray(Collecti 
>>
>> onProxyDefaultImpl.java:260)
>> at
>> de.ppi.neuwerk.repman.persistent.ojb.AuditOjb.getCreatedNodes(AuditOjb.java: 
>>
>> 157)
>>
>> With some effort, I tried also current CVS head, and the problem is still
>> there.
>>
>> Any ideas for a workaround?  I wonder if anybody else has this problem?!
>> I cannot image that we are the only ones who have primary-key fields with
>> FieldConversion
>> and who use m:n-Collections.
>>
>> Best regards,
>>  Olli
>>
>> P.S. I am committer myself, and I apologize for my long absence from 
>> active
>> participation.
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
>> For additional commands, e-mail: ojb-user-help@db.apache.org
>>
>>  
>>
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-user-help@db.apache.org
> 
> 

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


Re: non-equal Identities for primary-key fields with FieldConversion

Posted by "Ludovic Maitre (POP - Factory Part)" <lm...@factory-part.com>.
hello,

I have the same problem and use the following patch. Tell me if this 
help (and if this is safe!):
[line added are precede by LMA]
    protected void associateBatched(Collection owners, Collection 
children, Collection mToNImplementors)
    {
        CollectionDescriptor cds = getCollectionDescriptor();
        PersistentField field = cds.getPersistentField();
        //LMA: Use a field conversion if necessary
        //[Solve the potential problem described above]
        FieldConversion fc = 
cds.getClassDescriptor().getPrimaryKey().getFieldConversion();
        PersistenceBroker pb = getBroker();
        Class ownerTopLevelClass = 
pb.getTopLevelClass(getOwnerClassDescriptor().getClassOfObject());
        Class childTopLevelClass = 
pb.getTopLevelClass(getItemClassDescriptor().getClassOfObject());
        Class collectionClass = cds.getCollectionClass(); // this 
collection type will be used:
        HashMap childMap = new HashMap();
        HashMap ownerIdsToLists = new HashMap();

        // initialize the owner list map
        for (Iterator it = owners.iterator(); it.hasNext();)
        {
            Object owner = it.next();
            ownerIdsToLists.put(new Identity(owner, pb), new ArrayList());
        }

        // build the children map
        for (Iterator it = children.iterator(); it.hasNext();)
        {
            Object child = it.next();
            childMap.put(new Identity(child, pb), child);
        }

        int ownerPkLen = getOwnerClassDescriptor().getPkFields().length;
        int childPkLen = getItemClassDescriptor().getPkFields().length;
        Object[] ownerPk = new Object[ownerPkLen];
        Object[] childPk = new Object[childPkLen];

        // build list of children based on m:n implementors
        for (Iterator it = mToNImplementors.iterator(); it.hasNext();)
        {
            Object[] mToN = (Object[]) it.next();
            //LMA: Use the field conversion if it exist. We assume that 
the pk of the 2 objects are of the same type.
            //[solve the potential problem described by BRJ]
            if (fc!=null)
                    for (int i=0;i<mToN.length;i++)
                        mToN[i]=fc.sqlToJava(mToN[i]);
            System.arraycopy(mToN, 0, ownerPk, 0, ownerPkLen);
            System.arraycopy(mToN, ownerPkLen, childPk, 0, childPkLen);

            Identity ownerId = new Identity(null, ownerTopLevelClass, 
ownerPk);
            Identity childId = new Identity(null, childTopLevelClass, 
childPk);

            // Identities may not be equal due to type-mismatch
            Collection list = (Collection) ownerIdsToLists.get(ownerId);
            Object child = childMap.get(childId);
            list.add(child);
        }

oliver.matz@ppi.de wrote:

>Hello,
>
>I am currently porting our application from OJB 1.0.0rc4 to OJB 1.0.0
>
>A new problem has been introduced since then in
>MtoNCollectionPrefetcher.associateBatched,
>as Jakob points out in this source's javadoc:
>
>BRJ: There is a potential problem with the type of the pks used to build the
>Identities.
> * When creating an Identity for the owner, the type of pk is defined by the
>instvars 
> * representing the pk. When creating the Identity based on the
>mToNImplementor the
> * type of the pk is defined by the jdbc-type of field-descriptor of the
>referenced class.
> * This type mismatch results in Identities not being equal. <br>
> * Integer[] {10,20,30} is not equal Long[] {10,20,30}
>
>In my application, I use primary keys of type Long mapped to BigDecimal.
>The issue then results in the stacktrace below.
>
>java.lang.NullPointerException
> at
>org.apache.ojb.broker.accesslayer.MtoNCollectionPrefetcher.associateBatched(
>MtoNCollectionPrefetcher.java:408)
> at
>org.apache.ojb.broker.accesslayer.MtoNCollectionPrefetcher.prefetchRelations
>hip(MtoNCollectionPrefetcher.java:94)
> at
>org.apache.ojb.broker.core.QueryReferenceBroker$PBPrefetchingListener.prefet
>ch(QueryReferenceBroker.java:873)
> at
>org.apache.ojb.broker.core.QueryReferenceBroker$PBCollectionProxyListener.be
>foreLoading(QueryReferenceBroker.java:930)
> at
>org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.beforeLoading(Co
>llectionProxyDefaultImpl.java:182)
> at
>org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.getData(Collecti
>onProxyDefaultImpl.java:425)
> at
>org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.toArray(Collecti
>onProxyDefaultImpl.java:260)
> at
>de.ppi.neuwerk.repman.persistent.ojb.AuditOjb.getCreatedNodes(AuditOjb.java:
>157)
>
>With some effort, I tried also current CVS head, and the problem is still
>there.
>
>Any ideas for a workaround?  I wonder if anybody else has this problem?!
>I cannot image that we are the only ones who have primary-key fields with
>FieldConversion
>and who use m:n-Collections.
>
>Best regards,
>  Olli
>
>P.S. I am committer myself, and I apologize for my long absence from active
>participation.
>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
>For additional commands, e-mail: ojb-user-help@db.apache.org
>
>  
>


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