问题
From my reading of the JPA 2.0 spec, the following should be valid:
select e.employeeId, new com.foo.Custom(e.employeeName, e.employeeCity) from Employee e
However, Hibernate complains about this query, citing the first comma. If I reverse the order of the selected expressions, it still complains:
select new com.foo.Custom(e.employeeName, e.employeeCity), e.employeeId from Employee e
But if I select only the constructor expression, it works:
select new com.foo.Custom(e.employeeName, e.employeeCity) from Employee e
I have searched in vain for examples on the web of JPQL queries that use constructor expressions that are not the sole expressions in the SELECT clause, even though the grammar in the JPA 2.0 spec appears to allow them. Does anyone know of a workaround for this, other than to create a different, monolithic custom class that encapsulates all data in a selected record?
回答1:
Tried your query on Hibernate-JPA (org.hibernate.hql.internal.ast.QuerySyntaxException
) and on EclipseLink (OK).
Next, I found similar 2008-year bug on Hibernate. Those query also runs OK on EclipseLink.
I think, it is a bug of Hibernate (HQL).
Documentation says,
JPQL is a heavily-inspired-by subset of HQL. A JPQL query is always a valid HQL query, the reverse is not true however.
In fact, Hibernate parses JPQL query with the same grammar/parser as HQL.
Next, look in source file (HQL ANTLR grammar), I see this:
selectClause
: SELECT^ // NOTE: The '^' after a token causes the corresponding AST node to be the root of the sub-tree.
{ weakKeywords(); } // Weak keywords can appear immediately after a SELECT token.
(DISTINCT)? ( selectedPropertiesList | newExpression | selectObject )
;
newExpression
: (NEW! path) op:OPEN^ {#op.setType(CONSTRUCTOR);} selectedPropertiesList CLOSE!
;
So, now it is clear, why Hibernate throws QuerySyntaxException
.
When using Hibernate JPQL, we are forced to choose one of three options:
- properties list (i.e.
e.employeeName, e.employeeCity
) - constructor expression (i.e.
new com.foo.Custom(e.employeeName, e.employeeCity)
) - object identifier from 'FROM' clause (i.e.
e
)
来源:https://stackoverflow.com/questions/15821074/jpql-hibernate-limitation-using-constructor-expression-in-select