persistence@glassfish.java.net

Re: JPQL: create ReadAllQuery for simple SELECT queries

From: Michael Bouschen <Michael.Bouschen_at_Sun.COM>
Date: Wed, 29 Nov 2006 12:08:37 +0100

Hi Tom,

thanks for figuring out! So I will keep the code that checks for a fetch
join and then generates a ReportQuery instance.

Attached you find an updated version of my changes to fix 1519. The jar
includes all the changes, but only one file has been changed compared to
the previous version I sent around. I modified class VariableNode to use
the API addJoinedAttribute(Expression) if the query instance is not a
ReportQuery. Today this code will not be called, but it is ready to go
as soon as we generate ReadAllQuery even in the fetch join case.

Regards Michael
> Hi Michael,
>
> I found the reason for the fetch join issue. The way we are
> returning items for the fetch join is actually dictated by the
> specification. (see section 4.4.5.3)
>
> What that means is that for the time being, we will likely have to
> generate a ReportQuery on fetch join. I plan on entering an
> Enhancement request to add a ReadAllQuery option that allows results
> to be returned in the same way. At that time, we can update the JPQL
> parser.
>
> I appologize for causing this extra work before it can actually be used.
>
> -Tom
>
>
>
> Michael Bouschen wrote:
>
>> Hi Tom,
>>
>> good point! I was not aware of the other API
>> addJoinedAttribute(Expression) that allows fetch join support for
>> ReadAllQuerys.
>>
>> I changed the query compiler accordingly, such that it supports
>> generating a ReadAllQuery with fetch joins. But now I run into a
>> problem with one of the tests in entity-persistence-tests:
>> JUnitEJBQLSimpleTestSuite.simpleJoinFetchTest. The test runs a JPQL
>> fetch join query and compares the result against a TopLink
>> ReportQuery. The ReportQuery result includes duplicated entities
>> where the corresponding ReadAllQuery does not include duplicates.
>>
>> Attached you find a small test application showing the difference. It
>> has two entity classes: Customer and Order. The test creates one
>> Customer with two Order instances and persist them. It then runs a
>> ReportQuery and a ReadAllQuery both representing the following JPQL
>> query "SELECT c FROM Customer c JOIN FETCH c.orders". The generated
>> SQL is equivalent (the identification variable names are swapped).
>> But the ReportQuery returns the Customer twice, where the
>> ReadAllQuery returns it only once. Here are the results:
>> ReportQuery:
>> - SQL
>> SELECT DISTINCT t0.ID, t0.NAME, t1.ID, t1.TOTAL_PRICE,
>> t1.CREATION_DATE, t1.CUST_ID
>> FROM CUSTOMER_TABLE t0, ORDER_TABLE t1 WHERE (t1.CUST_ID = t0.ID)
>> - Result [Customer(id=1, name=Michael), Customer(id=1, name=Michael)]
>>
>> ReadAllQuery:
>> - SQL
>> SELECT DISTINCT t1.ID, t1.NAME, t0.ID, t0.TOTAL_PRICE,
>> t0.CREATION_DATE, t0.CUST_ID
>> FROM ORDER_TABLE t0, CUSTOMER_TABLE t1 WHERE (t0.CUST_ID = t1.ID)
>> - Result: [Customer(id=1, name=Michael)]
>>
>> The test uses ddl-generation. Please adapt the persistence.xml under
>> src/META-INF to your environment, if you want to run the test.
>>
>> Regards Michael
>>
>>
>>> Hi Michael,
>>>
>>> 'Just one comment.
>>>
>>> Fetch joins could be an issue since they are supported in
>>> ReadAllQuery, but with different API. See
>>> ObjectLevelReadQuery.addJoinedAttribute(Expression). How difficult
>>> would it be to allow fetch joins to work on ReadAllQueries?
>>>
>>> -Tom
>>>
>>> Michael Bouschen wrote:
>>>
>>>
>>>> Hi Tom, hi Jielin,
>>>>
>>>> attached you find my changes to fix issue 1519 "JPQL: create a
>>>> ReadAllQuery for simple queries":
>>>> https://glassfish.dev.java.net/issues/show_bug.cgi?id=1519
>>>>
>>>> This change allows to map a simple SELECT query to a ReadAllQuery
>>>> instance, where other SELECT queries are mapped to a ReportQuery. A
>>>> query falls into the ReadAllQuery category, if
>>>> - the SELECT clause consists of a single expression
>>>> - the SELECT clause expression is an identification variable w/o
>>>> projection (which means the query returns entities)
>>>> - the identification variable is defined as range variable w/o
>>>> FETCH JOINs and is the base of the generated TopLink query instance.
>>>>
>>>> Thanks!
>>>>
>>>> Regards Michael
>>>>
>>>>
>>>>
>>>>
>>
>>
>>
>