Search code examples
sqlhibernatejpanamingreserved-words

Reserved keyword as identifier in JPA query


I defined multiple JPA named queries this way:

SELECT group FROM FOO_Group group WHERE group.valid = :valid ORDER BY group.date

Even though group is a reserved keyword in SQL, this never seemed to bother Hibernate.

Now, however, I had to define a named query that joins two tables:

SELECT group FROM FOO_User user JOIN user.group group WHERE group.valid = :valid ORDER BY group.date

This time the query fails and Hibernate states that BY was expected (as in GROUP BY), but WHERE was found.

I know that using reserved keywords as column, table or entity names is generally a bad idea. But I wonder, why it did not cause any trouble in my old queries, but now fails in the joining query. Is there any syntax that allows me to use group in the new query as well? I tried JOIN user.group AS group, but that did not work out as expected.

Right now, all I can do is renaming the identifier:

SELECT g FROM FOO_User user JOIN user.group g WHERE g.valid = :valid ORDER BY g.date

Solution

  • You should distinguish SQL key words and JPQL/HQL reserved identifiers.

    You can use SQL quoted identifiers for column/table names.

    But according to the JPA specification (see section 4.4.1 Identifiers)

    Reserved identifiers must not be used as identification variables or result variables (see section 4.8).

    Your first query worked just by chance. The HQL grammar is specified here. As you can see from the HqlParser implementation the group belong to so called weak keywords (see the weakKeywords() method). So, the first query was tokenized in the following way:

    SELECT group               --> selectClause                
    FROM FOO_Group group       --> fromClause   (FROM^ { weakKeywords(); }) ...
    WHERE group.valid = :valid --> whereClause
    ORDER BY group.date        --> orderByClause
    

    But the second one:

    SELECT group             --> selectClause
    FROM FOO_User user       --> fromClause FROM^ { weakKeywords(); }
    JOIN user.group          ----> fromJoin ... JOIN^ (FETCH)? joinPath (asAlias)? ...
    group                    --> problem !!!
    WHERE group.valid = :valid
    ORDER BY group.date