|
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)
|
