persistence@glassfish.java.net

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

From: Michael Bouschen <Michael.Bouschen_at_Sun.COM>
Date: Tue, 27 Feb 2007 18:02:15 +0100

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