I am having a problem with Hibernate generating invalid SQL. Specifically, mixing and matching implicit and explicit joins. This seems to be an open bug.
However, I'm not sure why this is invalid SQL. I have come up with a small toy example that generates the same syntax exception.
CREATE TABLE Employee (
employeeID INT,
name VARCHAR(255),
managerEmployeeID INT
)
INSERT INTO Employee (employeeID, name) VALUES (1, 'Gary')
INSERT INTO Employee (employeeID, name, managerEmployeeID) VALUES (2, 'Bob', 1)
Both of these queries work. I realize there is a Cartesian product; that's intentional.
Explicit JOIN:
SELECT e1.name,
e2.name,
e1Manager.name
FROM Employee e1
CROSS JOIN Employee e2
INNER JOIN Employee e1Manager
ON e1.managerEmployeeID = e1Manager.employeeID
Implicit JOIN:
SELECT e1.name,
e2.name,
e1Manager.name
FROM Employee e1,
Employee e2,
Employee e1Manager
WHERE e1.managerEmployeeID = e1Manager.employeeID
This query does NOT work on MSSQL 2000/2008 or MySQL:
SELECT e1.name,
e2.name,
e1Manager.name
FROM Employee e1,
Employee e2
INNER JOIN Employee e1Manager
ON e1.managerEmployeeID = e1Manager.employeeID
In MS2000, I get the error:
The column prefix 'e1' does not match with a table name or alias name used in the query.
In MySQL, the error is:
Unknown column 'e1.managerEmployeeID' in 'on clause'.
Implicit joins exist as part of the Siebel object architecture. They are not explicitly defined using Siebel Tools. Unlike joins that you define in Siebel Tools, users can update the columns from implicit joins. Implicit joins exist for the following: All 1:1 (_X) extension tables and all relevant intersection tables.
The implicit join syntax is “old-style” syntax, where each join operation is defined implicitly via the WHERE clause, using the so-called join columns (see the second statement in Example 6.57). Note – Use of the explicit join syntax is recommended. This syntax enhances the readability of queries.
The "implicit join notation" simply lists the tables for joining, in the FROM clause of the SELECT statement, using commas to separate them. Thus it specifies a cross join, and the WHERE clause may apply additional filter-predicates (which function comparably to the join-predicates in the explicit notation).
It results in an error because according to the SQL standard, the JOIN
keyword has higher precedence than the comma. The sticky point is that table aliases are not usable until after the corresponding table has been evaluated in the FROM
clause.
So when you reference e1
in your JOIN...ON
expression, e1
doesn't exist yet.
Please stand by while I research Hibernate and find out if you can persuade it to use JOIN
in all cases.
Hmm. Everything at Hibernate.org seems to be redirecting to jboss.org. So no way to read HQL documentation online right now. I'm sure they'll figure out their name serving eventually.
This might be a bit off topic, because it doesn't concern hibernate at all, but the comment from Bill Karwin really opened my eyes. Instead of writing the implicit joining first, you need to do the explicit joining first. This syntax is especially interesting if you have multiple implicit joins.
Check the following example in MS SQL. Not all contacts have a country code defined, but all contacts have an attribute val which will be looked up in the table Tbl. So the intuitive solution will not work:
SELECT * FROM
contacts, Tbl
LEFT OUTER JOIN country ON CtryCod = country.CtryCod
WHERE val = Tbl.val
Instead you might rather want to use the following syntax:
SELECT * FROM
contacts LEFT OUTER JOIN country ON CtryCod = country.CtryCod,
Tbl
WHERE val = Tbl.val
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With