Синтаксис соединения JPQL / HQL для совместимости с EclipseLink и Hibernate

Я хотел бы иметь возможность поменять свою реализацию JPA между EclipseLink и Hibernate с помощью простого изменения свойства. Я могу сделать это нормально, но у меня возникают проблемы с проверкой именованного запроса. Используя EclipseLink, я должен написать объединение выборки следующим образом:

SELECT id 
FROM IndexDefinition id 
JOIN FETCH id.index 
JOIN id.index i
JOIN FETCH i.indexVersions

Но при проверке этого запроса с помощью Hibernate я получаю следующее исключение:

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list 

Поэтому я могу изменить запрос, чтобы он был дружественным к HQL, например:

SELECT id 
FROM IndexDefinition id 
JOIN FETCH id.index i
JOIN FETCH i.indexVersions

Но это вызывает следующее исключение в 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)

Я знаю, что могу использовать подсказки запросов на своем уровне DAO для выполнения выборочного соединения, но есть ли способ удовлетворить обе реализации JPA с помощью определенного синтаксиса выборочного соединения?


person timbotoolman    schedule 16.08.2010    source источник
comment
Какие именно версии Hibernate и EclipseLink вы используете? Первый запрос у меня отлично работает с Hibernate EM 3.4.0.GA.   -  person Pascal Thivent    schedule 16.08.2010
comment
Извините, в запросе пропущена строка. Я исправил с правкой. Я использую версию 3.5.1-Final hibernate-entitymanager.   -  person timbotoolman    schedule 16.08.2010


Ответы (1)


Похоже, вложенные соединения не поддерживаются JPA 1.0. Из спецификации JPA 1.0:

4.4.5.3 Соединения выборки

FETCH JOIN позволяет получить ассоциацию как побочный эффект выполнения запроса. FETCH JOIN указывается для сущности и связанных с ней сущностей.

Синтаксис для выборочного соединения:

fetch_join ::= [ LEFT [OUTER] | INNER ] JOIN FETCH join_association_path_expression

Ассоциация, на которую ссылается правая часть предложения FETCH JOIN, должна быть ассоциацией, принадлежащей объекту, возвращаемому в результате запроса. Не разрешается указывать переменную идентификации для объектов, на которые ссылается правая часть предложения FETCH JOIN, поэтому ссылки на неявно извлеченные объекты не могут появляться в другом месте запроса.

Следующий запрос возвращает набор отделов. В качестве побочного эффекта также извлекаются связанные сотрудники для этих отделов, даже если они не являются частью явного результата запроса. Постоянные поля или свойства служащих, которые активно извлекаются, полностью инициализируются. Инициализация свойств отношений извлекаемых сотрудников определяется метаданными для класса сущностей Employee.

SELECT d
FROM Department d LEFT JOIN FETCH d.employees
WHERE d.deptno = 1

Соединение выборки имеет ту же семантику соединения, что и соответствующее внутреннее или внешнее соединение, за исключением того, что связанные объекты, указанные в правой части операции соединения, не возвращаются в результате запроса или иным образом не упоминаются в запросе. Следовательно, например, если в отделе 1 пять сотрудников, приведенный выше запрос возвращает пять ссылок на сущность отдела 1.

Таким образом, хотя вложенные соединения могут поддерживаться некоторыми провайдерами JPA, их поведение не стандартизировано.

использованная литература

  • JPA 1.0 Specification
    • Section 4.4.5.3 "Fetch Joins"
  • JPA Wikibook
person Pascal Thivent    schedule 16.08.2010