jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: outer joins with ON conditions

From: Linda DeMichiel <linda.demichiel_at_oracle.com>
Date: Thu, 17 Mar 2011 11:13:34 -0700

On 3/17/2011 1:30 AM, Emmanuel Bernard wrote:
> On 16 mars 2011, at 20:15, Linda DeMichiel wrote:
>
>>
>> On 3/16/2011 3:46 AM, Emmanuel Bernard wrote:
>>> On 15 mars 2011, at 19:16, Linda DeMichiel wrote:
>>>> JPQL would be:
>>>>
>>>> FROM Cat as cat LEFT JOIN Kittens k ON k.bodyWeight > 10.0 AND k.parentName = cat.Name
>>> But in this case, the SQL would be
>>> from Cat c OUTER JOIN Kitten k ON c.id = k.parent AND c.name = k.parentName AND k.bodyWeight > 10.0
>>> which is one to many clause for what the user wants to do.
>> No, the above would not add c.id = k.parent to the SQL ON clause.
>>
>> Since we only defined JOIN that involves relationship navigation, we
>> can make this distinction.
>>
>
> Got it now, sorry for having been dense :)
>
> For completion, one case we would not be able to support is to map this full ON clause definition on an existing association at the object level.
>
> Instead of:
> String queryAssumingFullOnRewriting =
> "select c from Cat c left join fetch c.kittens on c.name = k.parentName AND k.bodyWeight > 10.0";
> TypedQuery<Cat> cats = em.createQuery( queryAssumingFullOnRewriting ).getResultList();
> for (Cat cat : cats) {
> Cat kittenJoinedByNameAndHealthy = cat.getKittens();
> doStuff(kittenJoinedByNameAndHealthy);
> }

We don't currently support this however, since fetch joins are not permitted to specify
an identification variable for objects referenced on the right side of the fetch
join clause. You've cheated a bit above by sneaking in the "k." :-)

We can still allow the use of ON with fetch joins, but it could reference the left
hand side only.

>
> People would need to use tuples
>
> String adHocOn =
> "select c,k from Cat c left join Cat k on c.name = k.parentName AND k.bodyWeight > 10.0";
> TypedQuery<Tuple> cats = em.createQuery( adHocOn ).getResultList();
> for (Tuple cat : cats) {
> Cat cat = (Cat) tuple.get(0);
> Cat kittenJoinedByNameAndHealthy = (Cat) tuple.get(1);
> doStuff(kittenJoinedByNameAndHealthy);
> }
>
> That's the only case I can think of when WITH vs ON could make sense.