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