Search code examples
querydsl

FROM missing on QueryDSL


I'm using QueryDSL v4.1.4 to do this query

.select(/*many fields*/)
.from(_product)
.join(_event).on(_product.event.eq(_event))
.join(_customer).on(_event.customer.eq(_customer))
.leftJoin(_person).on(_customer.person.eq(_person))
.leftJoin(_organization).on(_customer.organization.eq(_organization))
.where(/*many filters*/)

My code generate this SQL

SELECT --many fields
FROM product t3 
LEFT OUTER JOIN person t1 ON (t0.p_id = t1.p_id) 
LEFT OUTER JOIN organization t2 ON (t0.o_id = t2.o_id), 
event t4, 
customer t0
WHERE --many filters

But I would expect that this SQL will be generated (this SQL work fine in my DBMS)

SELECT --many fields
FROM product t3,
event t4, 
customer t0
LEFT OUTER JOIN person t1 ON (t0.p_id = t1.p_id) 
LEFT OUTER JOIN organization t2 ON (t0.o_id = t2.o_id)
WHERE --many filters

When trying to execute the query this exception occurs

missing FROM-clause entry for table "t0" (customer)

Failed ideas to fix it

  • Add all meta-models on from clause (this produces a useless and very heavy query)
  • I'm also use fetchJoin() to try to force a join over other but I have the same result (exception missing FROM-clause)

Exist any way to force the order that a join is applied on a query?


Solution

  • Why are there no joins on t3 or t4? I would have thought that this would result in the Cartesian product of these tables. Perhaps the joins are in the WHERE clause, which is not shown in the example? If so, why mix ANSI SQL and non ANSI SQL, rather than performing all the joins in the FROM clause? I don't think this is a querydsl issue but rather an issue with the SQL that you'd be best resolving first.

    To generate the SQL requested in your question, this should do the trick. However, you should refactor your query to do ANSI style joins in the FROM clause and querydsl will "just work".

    .select(/*many fields*/)
    .from(_product)
    .from(_event)
    .from(_customer)
    .leftJoin(_person).on(_customer.person.eq(_person))
    .leftJoin(_organization).on(_customer.organization.eq(_organization))
    .where(/*many filters*/)
    

    EDIT

    In the comments, Esvin points out there is a varargs version of the from method, so the three calls to the standard version of the from method can be reduced to one: .from(_product, _event, _customer)