Как покинуть объединение, чтобы выбрать нескольких детей в Hibernate? - PullRequest
17 голосов
/ 07 марта 2012

Я работаю с hibernate, и у меня возникают проблемы при создании hql-запроса, который выбирает всех дочерних элементов моего объекта.

Например: у пользователя объекта есть список автомобилей и список друзей.

Чтобы получить пользователя с его автомобилями, я бы использовал следующий запрос:

from User u left join fetch u.cars where u.id = ?

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

from User u left join fetch u.cars left join fetch u.friends where u.id = ?

Но это дает мне следующую ошибку:

HibernateException: невозможно одновременно получить несколько пакетов

Теперь мой вопрос: как правильно выбрать нескольких детей в спящем режиме?

Ответы [ 3 ]

12 голосов
/ 07 марта 2012

Не более одной детской коллекции должна быть сумка (т.е. объявленная в виде списка). Объявите другие коллекции как Наборы, и это будет работать.

Остерегайтесь, однако, что выполнение таких выборочных соединений делает декартово произведение рядов. Если обе коллекции имеют 100 элементов, такой запрос извлекает 10 000 строк из базы данных. Иногда эффективнее выполнить первый запрос, который выбирает одну коллекцию, и второй, который выбирает другую (что, таким образом, уменьшает количество извлекаемых строк до 200). Это также способ избежать вашей проблемы:

select u from User u left join fetch u.cars where u.id = :id;
select u from User u left join fetch u.friends where u.id = :id;
8 голосов
/ 20 апреля 2012

Вы только что достигли проблемы с коллекцией / списком (сумкой).

Вот ссылка на официальный «выпуск» Hibernate по этому поводу: https://hibernate.atlassian.net/browse/HHH-1718. Как видите, он был открытв 2006 году и все еще открыт.

В дополнение к тому, что предлагает JB Nizet, я предлагаю вам использовать Set вместо Collection или List в вашей модели (если вы можете), в противном случае вы также можете указать свою коллекцию / списоккак FetchMode.SUBSELECT и в качестве последнего варианта (болезненно реализовать), вы можете использовать @IndexColumn на своем @ OneToMany / @ ManyToMany.

Эта статья блога поможет вам в реализации решений: http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

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

Надеюсь, это поможет!

Редактировать: опечатка

0 голосов
/ 07 марта 2014

Невозможно, так как это будет слишком тяжело для приложения / базы данных, вам нужно создать 2 отдельных критерия и получать данные отдельно.

Cat cat = sess.createCriteria(Cat.class)
              .add(Restrictions.like("name", "F%"))
              .uniqueResult();

List kitten = sess.createCriteria(Kitten.class)
                  .add(Restrictions.eq("cat", cat))
                  .createCriteria("kittens")
                  .add(Restrictions.like("name", "F%"))
                  .list();

List mate = sess.createCriteria(Mate.class)
                .add(Restrictions.eq("cat", cat))
                .createCriteria("mate")
                .add(Restrictions.like("name", "F%"))
                .list();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...