Как выйти из списка, чтобы получить несколько дочерних элементов в Hibernate?

Я работаю с 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: невозможно одновременно получить несколько пакетов

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

Ответы

Ответ 1

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

Остерегайтесь, однако, что выполнение таких сборок fetch делает картографическое произведение строк. Если в обеих коллекциях имеется 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;

Ответ 2

Вы просто попали в проблему Collection/List (bag).

Вот ссылка на официальную "проблему" 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

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

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

Изменить: опечатка

Ответ 3

Невозможно, поскольку это слишком тяжело для приложения/базы данных, вам нужно создать 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();