When persisting an object with a compound identity that includes a detached field that itself has a compound identity, the following error is generated:
[2008-01-11 11:42:18,354]DEBUG400718[main] - org.jpox.util.Log4JLogger.debug(Log4JLogger.java:60) -
INSERT INTO CHILD ("NAME",PARENT_GRANDPARENT_NAME_OID_OID,PARENT_NAME_OID) VALUES (<'child1'>,<null>,<null>)
[2008-01-11 11:42:18,356] WARN400720[main] - org.jpox.util.Log4JLogger.warn(Log4JLogger.java:98) -
[JPOX-052208] Insert of object "
phmpro.detachtest.Child@1b1deea" using statement
"INSERT INTO CHILD ("NAME",PARENT_GRANDPARENT_NAME_OID_OID,PARENT_NAME_OID) VALUES (?,?,?)"
failed : At least one parameter to the current statement is uninitialized.
Exception in thread "main" javax.jdo.JDODataStoreException: [JPOX-052208] Insert of object
"
phmpro.detachtest.Child@1b1deea" using statement
"INSERT INTO CHILD ("NAME",PARENT_GRANDPARENT_NAME_OID_OID,PARENT_NAME_OID) VALUES (?,?,?)"
failed : At least one parameter to the current statement is uninitialized.
at org.jpox.jdo.JPOXJDOHelper.getJDOExceptionForJPOXException(JPOXJDOHelper.java:289)
at org.jpox.jdo.AbstractPersistenceManager.jdoMakePersistent(AbstractPersistenceManager.java:646)
at org.jpox.jdo.AbstractPersistenceManager.makePersistent(AbstractPersistenceManager.java:666)
at phmpro.detachtest.DetachmentTester.save(DetachmentTester.java:39)
at phmpro.detachtest.DetachmentTester.main(DetachmentTester.java:24)
My object hierarchy is, roughly:
Child[name, parent], Parent[name, grandparent], Grandparent[name]
Where all fields in each class are part of a compound PK with a custom ID class.
I've done some debugging, and found the following exception is thrown before that one (but doesn't get logged):
NullPointerException.<init>() line: 36 [local variables unavailable]
Parent.jdoCopyKeyFieldsFromObjectId(PersistenceCapable$ObjectIdFieldConsumer, Object) line: not available
PersistenceCapableMapping.setObjectAsValue(ObjectManager, Object, int[], Object, StateManager, int) line: 602
PersistenceCapableMapping.setObject(ObjectManager, Object, int[], Object, StateManager, int) line: 327
ParameterSetter.storeObjectField(int, Object) line: 142
JDOStateManagerImpl(AbstractStateManager).providedObjectField(PersistenceCapable, int, Object) line: 752
Child.jdoProvideField(int) line: not available
Child.jdoProvideFields(int[]) line: not available
JDOStateManagerImpl.provideFields(int[], FieldManager) line: 2600
InsertRequest.execute(StateManager) line: 251
ClassTable.insert(StateManager) line: 2888
RDBMSManager(MappedStoreManager).insertObject(StateManager) line: 180
JDOStateManagerImpl.internalMakePersistent() line: 3108
JDOStateManagerImpl.makePersistent() line: 3088
ObjectManagerImpl.persistObjectInternal(Object, FieldValues, StateManager, int, int) line: 1166
ObjectManagerImpl.persistObject(Object) line: 1017
JDOPersistenceManager(AbstractPersistenceManager).jdoMakePersistent(Object) line: 641
JDOPersistenceManager(AbstractPersistenceManager).makePersistent(Object) line: 666
DetachmentTester.save(PersistenceManagerFactory, Object) line: 39
DetachmentTester.main(String[]) line: 24
This exception is thrown because the PersistenceCapable instance is detached and jdoCopyKeyFieldsFromObjectId(...) requires the instance to have a Persistence Manager before being called (when the instance has a compound id that includes another PC instance).
In JPOX's PersistenceCapableMapping.setObjectAsValue(...) method, shouldn't [code]value[/value], when passed in be re-attached if it was a detached instance to begin with?
What's happening in my test case is that Child.parent is required to persist the Child instance, so InsertRequest.execute(...) calls the Child's JDOStateManagerImpl.provideFields(...) method. When this eventually gets down to the PCM.setObjectAsValue(...) method, though, the Child.parent field has never been re-attached and so when it calls the Parent's jdoCopyKeyFieldsFromObjectId(...) method, which expects its jdoGetPersistenceManager() to return something, a NullPointerException is thrown.
My test case is on another computer and I'll attach it right after I clean it up to match the requirements.