Как эффективно запросить три связанные таблицы (JPA-QL) - PullRequest
1 голос
/ 12 октября 2009

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

Поначалу может показаться, что-то вроде select a from A as a join fetch a.b join fetch a.c, но это создает огромный продукт, если число объектов B и C велико. Распространение этого на другие связанные объекты делает запрос совершенно необоснованным.

Если я оставлю JPA для своих собственных устройств, я получу n + 1 выбор, когда он хочет получить доступ к объектам B и C.

Я думал, что сделаю запрос выборки соединения B, а затем выборки соединения C, но это не сработает, поскольку дает мне два List<A> результата, каждый с половиной информации.

Это довольно простой запрос в терминах SQL, и я разочарован, что не существует очевидного способа справиться с этим. Я что-то упустил?

Провайдер является основой toplink

Ответы [ 2 ]

1 голос
/ 12 октября 2009

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

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

JPA не предназначен для замены SQL. Это устраняет это объектно-реляционное несоответствие. Если у вас нет объектов, просто перейдите в JDBC и SQL.

Я не знаю, что представляют ваши таблицы, но если вы думаете об объектах, вам следует поговорить об отношениях 1: m и m: n. Если у вас есть такие данные, вы можете использовать кэширование, ленивое извлечение и выборку для оптимизации заполнения объектов.

ОБНОВЛЕНИЕ: напишите запрос, чтобы у каждого продукта были свои параметры и прайс-листы в виде отношений 1: m, и вы всегда готовы к поиску. Это позволит избежать проблемы (n + 1).

Как вы можете сказать, что отношения и страстное увлечение здесь не помогают?

Попробуйте выразить отношения в объектах, и JPA покажет вам SQL, который он генерирует, и сравните его с тем, что вы написали бы. Если это удовлетворительно, пойти на это. Если нет, перейдите в JDBC и посмотрите, сможете ли вы добиться большего успеха.

0 голосов
/ 12 октября 2009

Интересно, почему вы говорите, что это довольно просто с точки зрения SQL. Разве вы не получили бы декартово произведение?


Использование провайдера Hibernate для JPA, упомянутый вами вариант работает:

запрос A выборка B, затем A выборка C C

У вас есть два списка одинаковых значений, вы используете только одно, и это нормально (вам просто нужно ЛЕВОЕ соединение).


В Hibernate вы также можете попросить извлечь недостающие данные во втором запросе.

Использовать fetch="subselect".

См. https://www.hibernate.org/315.html


ОБНОВЛЕНО после комментария оригинального плаката:

В Java вы также можете сделать это вручную .

  1. Получить As с их коллекциями Bs в списке под названием entityAs.
  2. Получение As с их коллекциями Cs (повторное использование части запроса или использование идентификаторов).
  3. Создать карту структуры данных> для второго запроса (для повышения производительности, чтобы избежать внутреннего цикла).
  4. Цикл по списку entityAs, используя карту для установки набора C для каждого экземпляра A.

Это также будет иметь хорошую производительность.

Если вы несколько раз сталкивались с этой потребностью, вы можете написать параметризованный метод, который сделает это за вас, поэтому вы будете кодировать его только один раз.

Как прокомментировал Исходный плакат, вам необходимо отсоединить все сущности A от entityAs перед их изменением, чтобы быть уверенным, что в базу данных не будет отправлено обновление ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...