I have investigated this problem a little more and have found that the following change fixes the problem:
 
In TransactionContext.java in the following method commenting out the line marked with ***** fixes the problem.
The new object is not fully created until the commit so the creating flag should not be changed here.  Since I am not familiar with the overall function I am not sure if this change breaks something else.  Can someone please take a look and check if this is really a bug fix ? 
 
Help is greatly appreciated.
 
public synchronized void update( LockEngine engine, ClassMolder molder, Object object, OID depended )
    throws DuplicateIdentityException, ObjectModifiedException,
    ClassNotPersistenceCapableException, PersistenceException {
boolean walk = false;
    if ( !_creating ) {
      walk = true;
      _creating = true;
    }
    markUpdate( engine, molder, object, depended );
 
    // markUpdate will actually update object loaded/create from preious
    // transaction, or it might marked some object to be created.
    // However, because some objects contains foreign key are key
    // generated, such object should be created after some other.
    // We iterate all object and creating object according the priority.
    int         priority  = 0;
    int         nextPrior = 0;
    for ( boolean nextCreate=walk; nextCreate; priority=nextPrior ) {
      Enumeration enum = _objects.elements();
      nextCreate = false;
      while ( enum.hasMoreElements() ) {
        ObjectEntry enumEntry = (ObjectEntry) enum.nextElement();
        try {
          if ( enumEntry.creating && !enumEntry.deleted ) {
            if ( enumEntry.molder.getPriority() <= priority ) {
              if ( _callback != null ) {
                _callback.creating( enumEntry.object, _db );
              } else if ( enumEntry.molder.getCallback() != null ) {
                enumEntry.molder.getCallback().creating( enumEntry.object, _db );
              }
              // Must perform creation after object is recorded in transaction
              // to prevent circular references.
              OID oid = enumEntry.engine.create
                ( this, enumEntry.oid, enumEntry.object );
 
              if ( oid.getIdentity() == null )
                throw new IllegalStateException("oid.getIdentity() is null after create!");
 
              // rehash the object entry, in case of oid changed
              ObjectEntry entry = rehash( enumEntry.object, oid );
 
              entry.created = true;
              //entry.creating = false; *****
              if ( _callback != null ) {
                _callback.using( entry.object, _db );
                _callback.created( entry.object );
              } else if ( enumEntry.molder.getCallback() != null ) {
                enumEntry.molder.getCallback().using( entry.object, _db );
                enumEntry.molder.getCallback().created( entry.object );
              }
            } else {
              nextPrior = Math.min( priority+1, enumEntry.molder.getPriority() );
              nextCreate = true;
            }
          }
        } catch ( Exception except ) {
          if ( _callback != null ) {
            _callback.releasing( enumEntry.object, false );
          } else if ( molder.getCallback() != null ) {
            molder.getCallback().releasing( enumEntry.object, false );
          }
          removeObjectEntry( enumEntry.object );
          if ( except instanceof DuplicateIdentityException )
            throw (DuplicateIdentityException) except;
          if ( except instanceof PersistenceException )
            throw (PersistenceException) except;
          except.printStackTrace();
          throw new PersistenceException( Messages.format("persist.nested",except) );
        }
      }
    }
 
    if ( walk ) {
      // after we create the objects, some cache may invalid because the
      // relation are cached on both side. So, we updateCache if it is
      // marked to be update from the markCreate state
      Enumeration enum = _objects.elements();
      while ( enum.hasMoreElements() ) {
        ObjectEntry enumEntry = (ObjectEntry) enum.nextElement();
        if ( enumEntry.created && enumEntry.updateCacheNeeded ) {
          enumEntry.engine.updateCache( this, enumEntry.oid, enumEntry.object );
          enumEntry.updateCacheNeeded = false;
        }
      }
      _creating = false;
    }
  }
 
 
 
 
 
Thanks Thomas, the fix makes things a little better. I am still having the following problem:
 
ITEM # 1
I load a parent from the database which has an associated 1:1 related child instance. Now I want to break the relationship between the parent and its associated child and relate the parent to a new child. When I try to do this I get the exception below.
ITEM # 2
In order to break the relationship and cause the old child to be deleted, do I have to first call update with the parent's child set to null  or can I just call update with the parent pointing to a new child ?
 
[NCS] Castor: Creating Parent (null)
[NCS] Castor: Creating Child (null)
[NCS] SELECT "PARENT"."OID","PARENT"."VALUE","CHILD"."OID" FROM "PARENT","CHILD" WHERE "PARENT"."OID"="CHILD"."PARENTOID"(+)
[NCS] Castor: Loading Child (1285)
[NCS] Castor: Loading Parent (1284)
[NCS] Castor: Storing Child (1285)
[NCS] SELECT "PARENT"."OID","PARENT"."VALUE","CHILD"."OID" FROM "PARENT","CHILD" WHERE "PARENT"."OID"="CHILD"."PARENTOID"(+)
[NCS] Castor: Loading Child (1285)
[NCS] Castor: Loading Parent (1284)
[NCS] Castor: Loading Child (1285)
[NCS] Castor: Creating Child (0)
org.exolab.castor.jdo.PersistenceException: The identity of a data object of type Child, has been changed from 0 to 1,286 since it is loaded/create/update.
 at org.exolab.castor.persist.ClassMolder.preStore(ClassMolder.java:1120)
 at org.exolab.castor.persist.LockEngine.preStore(LockEngine.java:726)
 at org.exolab.castor.persist.TransactionContext.prepare(TransactionContext.java:1358)
 at org.exolab.castor.jdo.engine.DatabaseImpl.commit(DatabaseImpl.java:499)
 at OracleTest.test(OracleTest.java:185)
 at OracleTest.main(OracleTest.java:50)
----- Original Message -----
From: Thomas Yip
Sent: Friday, August 24, 2001 9:10 PM
Subject: Re: [castor-dev] PersistenceException in long transaction involving 1:1 Urgent!!!!!!

 

 

>Can someone please confirm that 1:1 relashinships are supposed to work in long transactions.

Yes. It is supposed to work. See also my reply to your another email.


>
I cannot get 1:1 work with the "depends" element in mapping file. I do have the required back references in the child class and am implementing the timestampable interface.
>
 
>
Also without the depends element, if the child reference is updated with a new reference,

>an exception the following exception occurs:

 

What do you mean updated with a new reference?

 

 

 

Thomas

 

Reply via email to