Gordon, could you review this?
Regards
- Wonseok
On 10/16/06, Wonseok Kim <guruwons_at_gmail.com> wrote:
>
> Hi team,
> I believe you had a good weekend.
>
> I'm trying to fix the below issue 1153. The situation and cause of this
> issue are explained in the below message, please see it.
>
> To fix this, I added a map member to ObjectBuilder, which holds the
> secondary key field(primary key field of the child table) and primary key
> field(of the root table) mappings.
>
> // Secondary key field to Primary key field map (joined inheritance or
> secondary table)
> protected Map primaryKeyFieldsBySecondaryField;
>
> This map is used in ObjectBuilder.extractValueFromObjectForField() to get
> the corresponding primary key field when the child entity's primary key
> field was given.
>
> /**
> * Extract the value of the primary key attribute from the specified
> object.
> */
> public Object extractValueFromObjectForField(Object domainObject,
> DatabaseField field, AbstractSession session) throws DescriptorException {
> // Allow for inheritance, the concrete descriptor must always be
> used.
> ClassDescriptor descriptor = null;//this variable will be assigned
> in the final
>
> if (getDescriptor().hasInheritance() && (domainObject.getClass()
> != getDescriptor().getJavaClass()) && ((descriptor = session.getDescriptor(domainObject)).getJavaClass()
> != getDescriptor().getJavaClass())) {
> return descriptor.getObjectBuilder().extractValueFromObjectForField(domainObject,
> field, session);
> } else {
> DatabaseMapping mapping = getMappingForField(field);
> if (mapping == null) {
> throw DescriptorException.missingMappingForField(field,
> getDescriptor());
> }
>
> // GF#1153
> // If this entity is a child entity with JOINED inheritance
> strategy and Embedded Id,
> // getting value with the primary key field of child table
> won't succeed
> // for AggregateObjectMapping which only knows fields of root
> entity's table.
> // Therefore we use the primary key field of the root entity.
> if(getDescriptor().isChildDescriptor() &&
> mapping.isAggregateObjectMapping()){
> DatabaseField primaryKeyField = (DatabaseField)
> getPrimaryKeyFieldsBySecondaryField().get(field);
> if(primaryKeyField != null) {
> field = primaryKeyField;
> }
> }
> return mapping.valueFromObject(domainObject, field, session);
> }
> }
>
> I also added a new test for this - it required new models in 'inheritance'
> package because there is no proper entity for this issue.
> All entity-persistence tests including the new test passed with this fix.
>
> There are diffs, all modified and new files in the attached file.
> Please review!
>
> Thanks
> - Wonseok Kim
>
> On 13 Oct 2006 11:54:28 -0000, guruwons_at_dev.java.net <
> guruwons_at_dev.java.net> wrote:
> >
> > https://glassfish.dev.java.net/issues/show_bug.cgi?id=1153
> >
> > ------- Additional comments from guruwons_at_dev.java.net Fri Oct 13
> > 11:54:28 +0000 2006 -------
> > This exception occurs for all types of relationships whose target is a
> > child
> > entity which has JOINED inheritance strategy and Embedded Id.
> >
> > Following are an exception example.
> > ----------
> > Caused by: Exception [TOPLINK-45] (Oracle TopLink Essentials - 9.1(Build )):
> > oracle.toplink.essentials.exceptions.DescriptorException
> > Exception Description: Missing mapping for field [ NATURALPERSON.ID].
> > Descriptor: RelationalDescriptor(jpatests.model.Guid -->
> > [DatabaseTable(PERSON)])
> > at
> >
> > oracle.toplink.essentials.exceptions.DescriptorException.missingMappingForField
> > (DescriptorException.java :885)
> > at
> >
> > oracle.toplink.essentials.internal.descriptors.ObjectBuilder.extractValueFromObjectForField
> > (ObjectBuilder.java:1584)
> > at
> >
> > oracle.toplink.essentials.mappings.AggregateObjectMapping.valueFromObject(
> > AggregateObjectMapping.java:912)
> > at
> >
> > oracle.toplink.essentials.internal.descriptors.ObjectBuilder.extractValueFromObjectForField
> > (ObjectBuilder.java:1587)
> > at
> >
> > oracle.toplink.essentials.mappings.OneToOneMapping.writeFromObjectIntoRow(
> > OneToOneMapping.java:1058)
> > at
> > oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildRow(
> > ObjectBuilder.java:732)
> > at
> > oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildRow (
> > ObjectBuilder.java:720)
> > at
> >
> > oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWrite
> > (DatabaseQueryMechanism.java:425)
> > at
> > oracle.toplink.essentials.queryframework.InsertObjectQuery.executeCommit(
> > InsertObjectQuery.java:74)
> > at
> >
> > oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedWrite
> > (DatabaseQueryMechanism.java:635)
> > at
> >
> > oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedInsert(
> > DatabaseQueryMechanism.java:599)
> > at
> >
> > oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWriteWithChangeSet
> > (DatabaseQueryMechanism.java:495)
> > at
> >
> > oracle.toplink.essentials.queryframework.WriteObjectQuery.executeCommitWithChangeSet(
> > WriteObjectQuery.java:130)
> > at
> >
> > oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWriteWithChangeSet
> > (DatabaseQueryMechanism.java:283)
> > at
> >
> > oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(
> > WriteObjectQuery.java:67)
> > at
> > oracle.toplink.essentials.queryframework.DatabaseQuery.execute(
> > DatabaseQuery.java:609)
> > at
> >
> > oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(
> > DatabaseQuery.java:536)
> > at
> >
> > oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery
> > (ObjectLevelModifyQuery.java:123)
> > at
> >
> > oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(
> > ObjectLevelModifyQuery.java:95)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery
> > (UnitOfWorkImpl.java:2218)
> > at
> > oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(
> > AbstractSession.java:937)
> > at
> > oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery
> > (AbstractSession.java:894)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(
> > CommitManager.java:254)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.CommitManager.commitAllObjectsWithChangeSet
> > (CommitManager.java:175)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(
> > AbstractSession.java:2638)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase
> > (UnitOfWorkImpl.java:1030)
> > at
> >
> > oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(
> > RepeatableWriteUnitOfWork.java:357)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet
> > (UnitOfWorkImpl.java:1112)
> > at
> >
> > oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(
> > RepeatableWriteUnitOfWork.java:82)
> > at
> >
> > oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume
> > (UnitOfWorkImpl.java:842)
> > at
> >
> > oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(
> > EntityTransactionImpl.java:90)
> > ... 26 more
> > ----------
> >
> > CAUSE
> >
> > If entity B is a child entity of entity A which has composite primary
> > key by
> > @EmbeddedId, the internal class descriptor of B inherit mappings from
> > the
> > descriptor of A. Therefore B has same AggregateObjectMapping instance of
> > entity
> > A, and the AggregateObjectMapping instance has only fields of entity A.
> > For
> > example, if the primary key fields of A are A.ID1 and A.ID2 (table 'A'),
> > and the
> > primary key fields of B are B.ID1 and B.ID2, the AggregateObjectMapping
> > has only
> > A.ID1 and A.ID2.
> >
> > If ObjectBuilder.extractValueFromObjectForField() is called to get
> > primary key
> > value of child entity B with B.ID1, the AggregateObjectMapping doesn't
> > find
> > corresponding mapping with B.ID1 because it only knows A.ID1 and A.ID2.
> > So an
> > Exception like belwo is thrown.
> >
> > [TOPLINK-45] oracle.toplink.essentials.exceptions.DescriptorException
> > Exception Description: Missing mapping for field [B.ID1].
> >
> > So we need to call ObjectBuilder.extractValueFromObjectForField() of
> > AggregateObjectMapping with the field A.ID1 instead of given B.ID1.
> >
> > I'm working on the fix.
> >
> >
>
>