We thought we would send this because someone else might have had this
problem.

We are using OJB as the OR mapping layer for a new product that must
interoperate with a legacy product.  In our database schema, most of our
primary keys and foreign key references are int's.  We also use foreign
key constraints to insure that the data in our database is valid.
Therefore, we needed to be able to write out a null to our integer
foreign key fields when there was no related object to be pointed to.
The problem we ran into with OJB is that there was no way to get a null
value into an int column.  You can't just write out a zero in the
foreign key field, as that will just get you a constraint violation.  
 
So we modified the OJB source to allow us to write out a null to the db
whenever it came across an integer foreign key reference that was zero.
We also made another change to OJB so that when it sees that an object
referenced by a reference descriptor is null, then the corresponding
foreign key field will be set to 0.  That in turn will cause a null to
be written to the column in the database row and all is well.

Note:  This is a long email because there is source at the bottom.  We
are using OJB 0.9 and Oracle 8i.

Let us know what you think.  Thanks.

---
Kurt Post & Julie T. Tran

------------------------------------------------------------------
Example:

--repository mapping-

<class-descriptor class="com.mactiveinc.po.AoBlind"
   table="AoBlindBox">
   <field-descriptor id="1"
      name="id"
      column="Id"
      jdbc-type="INTEGER"
      primarykey="true"/>
  <field-descriptor id="2"
      name="customerId"
      column="CustomerId"
      jdbc-type="INTEGER"/>
   <reference-descriptor
      name="relatedCustomer"
      class-ref="com.mactiveinc.po.CustomerPO">
      <foreignkey field-id-ref="2"/>
    </reference-descriptor>
</class-descriptor>

<class-descriptor class="com.mactiveinc.po.CustomerPO"
   table="Customer">
   <field-descriptor id="1"
      name="accountId"
      column="AccountId"
      jdbc-type="INTEGER"
      primarykey="true"
      autoincrement="true"/>
</class-descriptor>


--Calls to store your null foreign key reference (this will set the
customerId in AoBlind to null)--

AoBlind toBeEdited = new AoBlind();
try
{
     broker.beginTransaction();
     toBeEdited.setRelatedCustomer(null);
     broker.store(toBeEdited);
     broker.commitTransaction();
}
catch(Throwable t)
{
     broker.abortTransaction();
     t.printStackTrace();
}

-------------------------------------------------------------------

--OJB source we had to modify--
Firstly, in ClassDescriptor.java, we added a method
getObjectReferenceDescriptorByFieldId(int id) that returns an
ObjectReferenceDescriptor if there it is a foreign key.  The parameter
it takes is the field id (column number).  Then, we modified
getNonKeyValues() to call getObjectReferenceDescriptorByFieldId(int id)
and then test if it is an int or Integer and if there it is a zero then
we set the value to null thereby writing out a null.  We further
modified assertFkAssignment(Object obj, Object ref,
ObjectReferenceDescriptor rds) in PersistenceBrokerImpl.java.  We check
to see if the foreign key reference is null, then we check if it is an
integer, then we set the integer value to zero.

------------------------------------------------------------------------

/* *in ClassDescriptor.java */


/**
 * returns an Array with an Objects NON-PK VALUES
*/
public Object[] getNonKeyValues(Object o) throws
PersistenceBrokerException
{
        FieldDescriptor[] nonPkFields = getNonPkFields();
      Object[] result = new Object[nonPkFields.length];
      for (int i = 0; i < result.length; i++)
      {
                FieldDescriptor fmd = nonPkFields[i];
            PersistentField f = fmd.getPersistentField();
            Object cv = null;
            try
            {
                // retrieve the Objects value for the specified field
                cv = f.get(o);
                // handle autoincrement attributes if not filled
                if (fmd.isAutoIncrement())
                {
                    cv = getAutoIncrementValue(fmd, o, cv);
                }
                // apply type and value conversion
                cv = fmd.getFieldConversion().javaToSql(cv);
         /* * newly added * */
                if ( (f.getType() == int.class) || (f.getType() ==
Integer.class) )
                {
                    ObjectReferenceDescriptor ojr =
 
getObjectReferenceDescriptorByFieldId(fmd.getColNo());
                        if ( (ojr != null) && (cv.equals(new Integer(0))
) )
                        {
                            cv = null;
                        }
                }
        /* * newly added * */
            }
            catch (Throwable t)
            {
                LoggerFactory.getDefaultLogger().error(t);
                throw new PersistenceBrokerException(t);
            }
            result[i] = cv;
        }
        return result;
    }

/* *added new method to ClassDescriptor.java * */

/**
     * Get an ObjectReferenceDescriptor by Field ID
     * @param field descriptor id
     * @return ObjectReferenceDescriptor or null
     */
    public ObjectReferenceDescriptor
getObjectReferenceDescriptorByFieldId(int id)
    {
        Vector descr = getObjectReferenceDescriptors();
        int size = descr.size();
        ObjectReferenceDescriptor result = null;

        for (int i = 0; i < size; i++)
        {
            ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor)
descr.elementAt(i);
            Vector fKeyFields = ord.getForeignKeyFields();
            for (int fk_i = 0; fk_i < fKeyFields.size(); fk_i++)
            {
                Integer fieldId = (Integer)fKeyFields.elementAt(fk_i);

                if (fieldId.intValue() == id)
                {
                    if(ord.getForeignKeyValues(fieldId, this) == null)
                        result = ord;
                        break;
                }
            }
        }
        return result;
    }

------------------------------------------------------------------------
-

/* *PersistenceBrokerImpl.java * */

/* *old* */
private void assertFkAssignment(Object obj, Object ref,
ObjectReferenceDescriptor rds)
    {
        try
        {
            if ((!(obj instanceof VirtualProxy))
                && (!(obj instanceof Proxy))
                && (ref != null)
                && (!(ref instanceof VirtualProxy))
                && (!(ref instanceof Proxy)))
            {
                Identity refOID = new Identity(ref);
                ClassDescriptor refCld =
descriptorRepository.getDescriptorFor(ref.getClass());
                Object[] refPkValues = refCld.getKeyValues(ref);
                ClassDescriptor objCld =
descriptorRepository.getDescriptorFor(obj.getClass());
                FieldDescriptor[] objFkFields =
rds.getForeignKeyFieldDescriptors(objCld);
                FieldDescriptor fld = null;
                for (int i = 0; i < objFkFields.length; i++)
                {
                    fld = objFkFields[i];
                    fld.getPersistentField().set(obj, refPkValues[i]);
                }
            }
        }
        catch (Throwable t)
        {
            logger.error(t);
            throw new PersistenceBrokerException(t);
        }
    }

/* *modified* */
private void assertFkAssignment(Object obj, Object ref,
ObjectReferenceDescriptor rds)
    {
        try
        {
             /* *modified * */
             if ((!(obj instanceof VirtualProxy))
                && (!(obj instanceof Proxy))
            
                && (!(ref instanceof VirtualProxy))
                && (!(ref instanceof Proxy)))
            {
                if (ref != null)
                {
                    Identity refOID = new Identity(ref);
                    ClassDescriptor refCld =
descriptorRepository.getDescriptorFor(ref.getClass());
                    Object[] refPkValues = refCld.getKeyValues(ref);
                    ClassDescriptor objCld =
descriptorRepository.getDescriptorFor(obj.getClass());
                    FieldDescriptor[] objFkFields =
rds.getForeignKeyFieldDescriptors(objCld);
                    FieldDescriptor fld = null;
                    for (int i = 0; i < objFkFields.length; i++)
                    {
                        fld = objFkFields[i];
                        fld.getPersistentField().set(obj,
refPkValues[i]);
                    }
                }
                else
                {
                    ClassDescriptor objCld =
descriptorRepository.getDescriptorFor(obj.getClass());
                    FieldDescriptor[] objFkFields =
rds.getForeignKeyFieldDescriptors(objCld);
                    FieldDescriptor fld = null;
                    for (int i = 0; i < objFkFields.length; i++)
                    {
                        fld = objFkFields[i];
                        Class fldClass =
fld.getPersistentField().getType();
                        if ( (fldClass == int.class) || (fldClass ==
Integer.class) )
                        {
                            fld.getPersistentField().set(obj, new
Integer(0));
                        }
                        else
                        {
                            fld.getPersistentField().set(obj, null);
                        }

                    }
                }
   /* * modified * */
            }
        }
        catch (Throwable t)
        {
            logger.error(t);
            throw new PersistenceBrokerException(t);
        }
    }

We are using OJB as the OR mapping layer for a new product that must
interoperate with a legacy product.  In our database schema, most of our
primary keys and foreign key references are int's.  We also use foreign
key constraints to insure that the data in our database is valid.
Therefore, we needed to be able to write out a null to our integer
foreign key fields when there was no related object to be pointed to.
The problem we ran into with OJB is that there was no way to get a null
value into an int column.  You can't just write out a zero in the
foreign key field, as that will just get you a constraint violation.  
 

So we modified the OJB source to allow us to write out a null to the db
whenever it came across an integer foreign key reference that was zero.
We also made another change to OJB so that when it see that an object
referenced by a reference descriptor is null, then the corresponding
foreign key filed will be set to 0.  That in turn will cause a null to
be written to the column in the database row and all is well.  

------------------------------------------------------------------
Example:

--repository mapping-

<class-descriptor class="com.mactiveinc.po.AoBlind"
   table="AoBlindBox">
   <field-descriptor id="1"
      name="id"
      column="Id"
      jdbc-type="INTEGER"
      primarykey="true"/>
  <field-descriptor id="2"
      name="customerId"
      column="CustomerId"
      jdbc-type="INTEGER"/>
   <reference-descriptor
      name="relatedCustomer"
      class-ref="com.mactiveinc.po.CustomerPO">
      <foreignkey field-id-ref="2"/>
    </reference-descriptor>
</class-descriptor>

<class-descriptor class="com.mactiveinc.po.CustomerPO"
   table="Customer">
   <field-descriptor id="1"
      name="accountId"
      column="AccountId"
      jdbc-type="INTEGER"
      primarykey="true"
      autoincrement="true"/>
</class-descriptor>

Calls to store your null foreign key reference (this will set the
customerId in AoBlind to null):

AoBlind toBeEdited = new AoBlind();
try
{
     broker.beginTransaction();
     toBeEdited.setRelatedCustomer(null);
    broker.store(toBeEdited);
    broker.commitTransaction();
}
catch(Throwable t)
{
     broker.abortTransaction();
     t.printStackTrace();
}

-------------------------------------------------------------------

--OJB source we had to modify--
Firstly, in ClassDescriptor.java, we added a method
getObjectReferenceDescriptorByFieldId(int id) that returns an
ObjectReferenceDescriptor if there it is a foreign key.  The parameter
it takes is the field id (column number).  Then, we modified
getNonKeyValues() to call getObjectReferenceDescriptorByFieldId(int id)
and then test if it is an int or Integer and if there it is a zero then
we set the value to null thereby writing out a null.  We further
modified assertFkAssignment(Object obj, Object ref,
ObjectReferenceDescriptor rds) in PersistenceBrokerImpl.java.  We check
to see if the foreign key reference is null, then we check if it is an
integer, then we set the integer value to zero.

------------------------------------------------------------------------

/* *in ClassDescriptor.java */


/**
     * returns an Array with an Objects NON-PK VALUES
     */
    public Object[] getNonKeyValues(Object o) throws
PersistenceBrokerException
    {
        FieldDescriptor[] nonPkFields = getNonPkFields();
        Object[] result = new Object[nonPkFields.length];
        for (int i = 0; i < result.length; i++)
        {
            FieldDescriptor fmd = nonPkFields[i];
            PersistentField f = fmd.getPersistentField();
            Object cv = null;
            try
            {
                // retrieve the Objects value for the specified field
                cv = f.get(o);
                // handle autoincrement attributes if not filled
                if (fmd.isAutoIncrement())
                {
                    cv = getAutoIncrementValue(fmd, o, cv);
                }
                // apply type and value conversion
                cv = fmd.getFieldConversion().javaToSql(cv);
         /* * newly added * */
                if ( (f.getType() == int.class) || (f.getType() ==
Integer.class) )
                {
                    ObjectReferenceDescriptor ojr =
 
getObjectReferenceDescriptorByFieldId(fmd.getColNo());
                        if ( (ojr != null) && (cv.equals(new Integer(0))
) )
                        {
                            cv = null;
                        }
                }
        /* * newly added * */
            }
            catch (Throwable t)
            {
                LoggerFactory.getDefaultLogger().error(t);
                throw new PersistenceBrokerException(t);
            }
            result[i] = cv;
        }
        return result;
    }

/* *added new method to ClassDescriptor.java * */

/**
     * Get an ObjectReferenceDescriptor by Field ID
     * @param field descriptor id
     * @return ObjectReferenceDescriptor or null
     */
    public ObjectReferenceDescriptor
getObjectReferenceDescriptorByFieldId(int id)
    {
        Vector descr = getObjectReferenceDescriptors();
        int size = descr.size();
        ObjectReferenceDescriptor result = null;

        for (int i = 0; i < size; i++)
        {
            ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor)
descr.elementAt(i);
            Vector fKeyFields = ord.getForeignKeyFields();
            for (int fk_i = 0; fk_i < fKeyFields.size(); fk_i++)
            {
                Integer fieldId = (Integer)fKeyFields.elementAt(fk_i);

                if (fieldId.intValue() == id)
                {
                    if(ord.getForeignKeyValues(fieldId, this) == null)
                        result = ord;
                        break;
                }
            }
        }
        return result;
    }

------------------------------------------------------------------------
-

/* *PersistenceBrokerImpl.java * */

/* *old* */
private void assertFkAssignment(Object obj, Object ref,
ObjectReferenceDescriptor rds)
    {
        try
        {
            if ((!(obj instanceof VirtualProxy))
                && (!(obj instanceof Proxy))
                && (ref != null)
                && (!(ref instanceof VirtualProxy))
                && (!(ref instanceof Proxy)))
            {
                Identity refOID = new Identity(ref);
                ClassDescriptor refCld =
descriptorRepository.getDescriptorFor(ref.getClass());
                Object[] refPkValues = refCld.getKeyValues(ref);
                ClassDescriptor objCld =
descriptorRepository.getDescriptorFor(obj.getClass());
                FieldDescriptor[] objFkFields =
rds.getForeignKeyFieldDescriptors(objCld);
                FieldDescriptor fld = null;
                for (int i = 0; i < objFkFields.length; i++)
                {
                    fld = objFkFields[i];
                    fld.getPersistentField().set(obj, refPkValues[i]);
                }
            }
        }
        catch (Throwable t)
        {
            logger.error(t);
            throw new PersistenceBrokerException(t);
        }
    }

/* *modified* */
private void assertFkAssignment(Object obj, Object ref,
ObjectReferenceDescriptor rds)
    {
        try
        {
             /* *modified * */
             if ((!(obj instanceof VirtualProxy))
                && (!(obj instanceof Proxy))
            
                && (!(ref instanceof VirtualProxy))
                && (!(ref instanceof Proxy)))
            {
                if (ref != null)
                {
                    Identity refOID = new Identity(ref);
                    ClassDescriptor refCld =
descriptorRepository.getDescriptorFor(ref.getClass());
                    Object[] refPkValues = refCld.getKeyValues(ref);
                    ClassDescriptor objCld =
descriptorRepository.getDescriptorFor(obj.getClass());
                    FieldDescriptor[] objFkFields =
rds.getForeignKeyFieldDescriptors(objCld);
                    FieldDescriptor fld = null;
                    for (int i = 0; i < objFkFields.length; i++)
                    {
                        fld = objFkFields[i];
                        fld.getPersistentField().set(obj,
refPkValues[i]);
                    }
                }
                else
                {
                    ClassDescriptor objCld =
descriptorRepository.getDescriptorFor(obj.getClass());
                    FieldDescriptor[] objFkFields =
rds.getForeignKeyFieldDescriptors(objCld);
                    FieldDescriptor fld = null;
                    for (int i = 0; i < objFkFields.length; i++)
                    {
                        fld = objFkFields[i];
                        Class fldClass =
fld.getPersistentField().getType();
                        if ( (fldClass == int.class) || (fldClass ==
Integer.class) )
                        {
                            fld.getPersistentField().set(obj, new
Integer(0));
                        }
                        else
                        {
                            fld.getPersistentField().set(obj, null);
                        }

                    }
                }
   /* * modified * */
            }
        }
        catch (Throwable t)
        {
            logger.error(t);
            throw new PersistenceBrokerException(t);
        }
    }


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to