Как получить все данные в одном запросе - PullRequest
11 голосов
/ 15 декабря 2011

У меня есть несколько объектов, которые запрашиваются с помощью JPA2 Criteria Query.

Я могу присоединиться к двум из этих сущностей и получить результат сразу:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<LadungRgvorschlag> criteriaQuery = criteriaBuilder.createQuery(LadungRgvorschlag.class);
Root<LadungRgvorschlag> from = criteriaQuery.from(LadungRgvorschlag.class);
Join<Object, Object> ladung = from.join("ladung");

from.fetch("ladung", JoinType.INNER);

Затем я пытаюсь присоединиться к дополнительной таблице:* я получаю следующую ошибку:

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias3,role=null,tableName=ladberechnet,tableAlias=ladberechn3_,origin=ladungen ladung1_,columns={ladung1_.id ,className=de.schuechen.beans.tms.master.LadBerechnet}}] [select generatedAlias0 from de.schuechen.beans.tms.master.LadungRgvorschlag as generatedAlias0 inner join generatedAlias0.ladung as generatedAlias1 inner join generatedAlias1.ladBerechnet as generatedAlias2 left join fetch generatedAlias1.ladBerechnet as generatedAlias3 inner join fetch generatedAlias0.ladung as generatedAlias4 where ( generatedAlias0.erledigt is null ) and ( generatedAlias0.belegart in (:param0, :param1) ) and ( generatedAlias1.fzadresse in (:param2, :param3) ) and ( generatedAlias1.zudatum<=:param4 ) and ( 1=1 ) order by generatedAlias0.belegart asc, generatedAlias1.fzadresse asc, generatedAlias1.zudatum asc, generatedAlias1.zulkw asc]

Как я могу сказать JPA / Hibernate, что он должен выбрать все объекты сразу?

Ответы [ 2 ]

11 голосов
/ 16 декабря 2011

С JPA 'некоторыми диалектами JPA' вы можете связывать выборки объединения, но я не думаю, что вы можете / должны делать как выборку, так и выборку объединения., если у нас есть Program, который имеет отношение «один ко многим» к Reward, который имеет отношение к Duration, следующий JPQL получит конкретный экземпляр с предварительно выбранными наградами и продолжительностью:

SELECT DISTINCT
    program
FROM
    Program _program
        LEFT JOIN FETCH
    _program.rewards _reward
        LEFT JOIN FETCH
    _reward.duration _duration
WHERE
    _program.id = :programId

}

С эквивалентным кодом Критерии:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Program> criteriaQuery = criteriaBuilder.createQuery(Program.class);
Root<Program> root = criteriaQuery.from(Program.class);

Fetch<Program, Reward> reward = root.fetch("rewards", JoinType.LEFT);
Fetch<Reward, Duration> duration = reward.fetch("duration", JoinType.LEFT);

criteriaQuery.where(criteriaBuilder.equal(root.get("id"), programId));

TypedQuery<program> query = entityManager.createQuery(criteriaQuery);

return query.getSingleResult();

Обратите внимание, что промежуточные переменные вознаграждение и продолжительность здесь не нужны, но они только для информационных целей.root.fetch("rewards", JoinType.LEFT).fetch("duration", JoinType.LEFT) будет иметь тот же эффект.

7 голосов
/ 15 декабря 2011

Что касается JPA, вы не можете связывать выборки соединений в запросах API Criteria (цитата из спецификации):

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

И это также не поддерживается в запросах JPQL:

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

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

С HQL это представляется возможным: Документация Hibernate EclipseLink не предоставляет такого расширения, поэтому синтаксис следующего запроса принимается Hibernate, но не EclipseLink:

SELECT a FROM A a LEFT JOIN FETCH a.bb b LEFT JOIN FETCH b.cc

В EclipseLink то же самое можно сделать с помощью подсказок к запросу .

...