persistence@glassfish.java.net

Re: JPQL: fix query issue when navigating through two level of embeddeds

From: Tom Ware <tom.ware_at_oracle.com>
Date: Wed, 28 Feb 2007 13:55:46 -0500

Hi Michael,

  I think I have discovered why you were seeing the issue with the
reference descriptor of the contact field showing up as null.

  The issue occurs because of the fact that Aggregates (Embeddables) are
handled in a special way in TopLink. Since Aggregates can be embedded
in multiple different objects, their descriptors are stored in 2 ways.

1. The project contains a shell of the descriptor that holds all the
information that is independant of where the Aggregate is Embedded.
2. The AggregateObjectMapping for each object that has the Aggregate
embedded has a clone of the descriptor held in the project that has been
updated with the information that is dependant of where the object is
embedded.

  When you lookup Submission's descriptor you get a concrete descriptor
for the Submission object. The Submission object has an
AggregateObjectMapping for company. Since the Submission descriptor is
a descriptor for an Entity, the AggregateObjectMapping holds the type of
descriptor described in #2 above and as a result, has all the information.

  When you lookup Company's descriptor, you get an AggregateDescriptor.
That descriptor contains an AggregateObjectMapping with a reference
descriptor of type #1 above. That descriptor does not contain all the
information.

  In order to get the correct information from the Company Descriptor,
you have to get the descriptor through the Submission descriptor. You
have to navigate through the Company mapping's descriptor and get the
descriptor from the AggregateObjectMapping to Contact.

-Tom

Michael Bouschen wrote:

>Hi Tom,
>
>I looked into issue 2463 "JPQL: cannot navigate through two level of
>embeddeds": https://glassfish.dev.java.net/issues/show_bug.cgi?id=2462.
>
>The following query runs into an exception at runtime:
> SELECT s.company.contact.firstName FROM Submission s
>The select clause navigates two levels of embedded instances: contact is
>embedded into company and company is embedded into submission. The query
>compiler sets an outer join flag for this query and this results in an
>exception that an outer join is invalid for a mapping
>AggregateObjectMapping.
>
>The query compiler needs to set the outer join flag in case a
>relationship field is selected in the SELECT clause. The current
>implementation checks whether a selected field is *not* mapped as
>DirectToFieldMapping. I changed this; now it checks whether it is a
>relationship field mapping. You find the changes in the attached jar
>fix2462.jar. Please have a look. I still need to add a test case to
>entity-persistence-tests. This requires extending an existing entity
>class, because today we do not have an entity with two level of embeddeds.
>
>However, I was wondering why the old code (checking that the field is
>not mapped as DirectToFieldMapping) did not work. I figured out that
>both embedded fields Submission.company and Company.contact are mapped
>as AggregateObjectMapping. But the reference descriptor of the aggregate
>mapping for the contact field is null. So the code does not get enough
>information to decide whether the firstName field in Contact is a
>DirectToFieldMapping or not.
>
>Attached you find a test case running the above query for testing. I
>also added a method printing the mapping of the two embedded fields and
>its reference descriptors:
> Submission.company
> MAPPING
>oracle.toplink.essentials.mappings.AggregateObjectMapping[company]
>REFERENCE DESCRIPTOR RelationalDescriptor(test.pojo.Company -->
>[DatabaseTable(SUBMISSION)])
> Company.contact
> MAPPING
>oracle.toplink.essentials.mappings.AggregateObjectMapping[contact]
>REFERENCE DESCRIPTOR null
>
>Regards Michael
>
>
>
>
>

-- 
Tom Ware
Principal Software Engineer
Oracle Canada Inc.
Direct: (613) 783-4598
Email: tom.ware_at_oracle.com