JPQL / HQL fetch join syntax for compatibility with EclipseLink & Hibernate
I would like to be able to swap my JPA implementation between EclipseLink & Hibernate with a simple property change. I can do this ok but what is causing me problems is the named query validation. Using EclipseLink I have to write fetch joins like so:
SELECT id
FROM IndexDefinition id
JOIN FETCH id.index
JOIN id.index i
JOIN FETCH i.indexVersions
But when validating this query using Hibernate I get the following exception:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
So I can change the query to be HQL friendly like so:
SELECT id
FROM IndexDefinition id
JOIN FETCH id.index i
JOIN FETCH i.indexVersions
But this then causes the following exception in EclipseLink:
Exception Description Syntax error parsing the query [IndexDefinition.getForIndex] SELECT id FROM IndexDefinition id JOIN FETCH id.index i, syntax error at [id].
Internal Exception MismatchedTokenException(78!=-1)
I know I can use query hints at my DAO level to perform a fetch 开发者_如何转开发join but is there a way of pleasing both JPA implementations with a specific fetch join syntax?
Well, it seems that nested joins are not supported by the JPA 1.0. From the JPA 1.0 specification:
4.4.5.3 Fetch Joins
A FETCH JOIN enables the fetching of an association as a side effect of the execution of a query. A FETCH JOIN is specified over an entity and its related entities.
The syntax for a fetch join is
fetch_join ::= [ LEFT [OUTER] | INNER ] JOIN FETCH join_association_path_expression
The association referenced by the right side of the FETCH JOIN clause must be an association that belongs to an entity that is returned as a result of the query. It is not permitted to specify an identification variable for the entities referenced by the right side of the FETCH JOIN clause, and hence references to the implicitly fetched entities cannot appear elsewhere in the query.
The following query returns a set of departments. As a side effect, the associated employees for those departments are also retrieved, even though they are not part of the explicit query result. The persistent fields or properties of the employees that are eagerly fetched are fully initialized. The initialization of the relationship properties of the employees that are retrieved is determined by the metadata for the Employee entity class.
SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.deptno = 1
A fetch join has the same join semantics as the corresponding inner or outer join, except that the related objects specified on the right-hand side of the join operation are not returned in the query result or otherwise referenced in the query. Hence, for example, if department 1 has five employees, the above query returns five references to the department 1 entity.
So, while nested joins might be supported by some JPA providers, the behavior is not standardized.
References
- JPA 1.0 Specification
- Section 4.4.5.3 "Fetch Joins"
- JPA Wikibook
- Nested Joins
精彩评论