powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate несколько HQL для заполнения сущности
18 сообщений из 18, страница 1 из 1
Hibernate несколько HQL для заполнения сущности
    #38406285
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, вопрос следующий.
Имеется 3 сущности, например "от балды" : Юзер , у него много Постов и у него много Категорий . Т.е. отношения Юзера один ко многим (к таблице постов и таблице категорий). Упрощённо

Код: java
1.
2.
3.
4.
5.
Class User {
    private List<Post> posts;
    private List<Category> categories;
    //другие свойства юзера(имя, логин и т д)
}

Аннотации отношений я опустил, но имеем ввиду что загрузка Lazy.
Вопрос: Как выбрать всех юзеров с уже заполнеными коллекциями posts и categories , при этом чтобы Hibernate выполнили всего 2 запроса, в первом выбрал всех юзеров с джоином постов, во втором всех юзеров с джоином категорий.

Пока получилось сделать только так:
Код: java
1.
2.
3.
4.
public List<User> findAll() {
        return session.getCurrentSession()
                .createQuery("from User u left join fetch u.posts").list();
    }


Но в этом случае при дальнейшем обращении к категориям будет иметь на каждого юзера по дополнительному запросу в БД (через LAZY загрузку), что не есть хорошо (юзеров много).

Теоретически нужно как-то выполнить 2 запроса в методе findAll():
Код: java
1.
2.
createQuery("from User u left join fetch u.posts")
createQuery("from User u left join fetch u.categories")


Но я, к сожалению, не знаю как.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406291
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так?
from User u
left join fetch u.posts
left join fetch u.categories
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406295
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406297
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SkyFireorg.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
Есть такое. Bag это не упорядоченая коллекция в хибернейт. Дело в том, что когда запускается join на несколько коллекций, то хибер не может из результатов запроса понять где какой user.id, чтобы правильно распихать результат по коллекциям.
Один из вариантов решения это замена Bag, на упорядоченый List. Для этого нужно в маппинге указать, как именно упорядочена коллекций.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406299
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://stackoverflow.com/questions/13334831/multiplebagfetchexception-thrown One way to do this is by specifying the Hibernate specific @IndexColumn or the JPA standard @OrderColumn on the relations.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406323
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

Вот с этим @OrderColumn у меня и проблема.
Класс User является "владельцем" связи с категориями, т.е.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Class User {

@Id
@Column(name = "id")
private String id;
    
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
@OrderColumn(name="user_id")
private List<Category> categories = new ArrayList<Category>();

...
}


класс Category ничего не знает о User.

При добавлении аннотации @OrderColumn(name="user_id") ловим следующее:
...hibernate.MappingException: Repeated column in mapping for collection: ru.example.unity.model.User.categories column: user_id

Возможно я вообще не правильно все понял. Поправьте пожалуйста.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406330
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давайте с моделью сначала разберемся.
То что категория ничего не знает о юзере - это мне понятно. Это логично.
Откуда вот только тогда у категории user_id - этого я не понимаю. Т.е. должно быть many-to-many.
И следующее. У всех категорий одного юзера - все user_id одинаковые. Поэтому сортировка по ним бессмысленна.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406353
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, пример с категориями не очень удачный и больше подходит для многие ко многим.
В действительности я "проецирую" этот упрощённый пример на свой реальный. Давайте условимся что "Юзеры" действительно относится к "Категориям" как многие к одному. Т.е.

Categories
iduser_idname12Авто22Вело33Вело44Спорт54Авто
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406356
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SkyFire"Юзеры" действительно относится к "Категориям" как многие к одному.
Точнее один ко многим конечно.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406358
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Логично попробовать
@OrderColumn(name="id")
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406382
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Теперь запрос строится верно (т.е. 2 лефт джоина обоих таблиц), но спустя 5 секунд:


17:09:40,244 WARN [org.hibernate.engine.loading.internal.LoadContexts] (http--127.0.0.1-8080-1) HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@4f96de53<;rs=org.postgresql.jdbc4.Jdbc4ResultSet@68577956>;
17:09:40,247 WARN [org.hibernate.engine.loading.internal.CollectionLoadContext] (http--127.0.0.1-8080-1) HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [100] entries
17:09:40,250 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/main].[unity-synch]] (http--127.0.0.1-8080-1) Servlet.service() for servlet unity-synch threw exception: java.lang.OutOfMemoryError: Java heap space

Сам SQL возвращает порядка 200 строк, теперь я в полном "ступоре" :(
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406392
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406856
пролетевший
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczfrom User u
left join fetch u.posts
left join fetch u.categories
Здесь засада на уровне SQL. такой запрос возвращает строки для каждого поста со всеми категориями ( картезианское произведение ). 100 постов и 100 категорий это уже 10000 строк. Потом хибер пытается их собрать вместе удаляя лишнее, поэтому и ругался на Bag.
Больше 2х таблиц в join пихать надо с большой осторожностью.
Лучше грузить lazy с Batch Fetch .
Оффтоп, недавно настраивали производительность в приложении и обнаружили что MS SQL Join для небольшой выборки делает в несколько раз медленнее, чем 2 отдельных запроса. основная база около 10 млн записей, на каждую в среднем 20 записей в дочерних таблицах. Для обработки выбираются 4 записи из основной таблицы, ц дочерними коллекциями. Удаление любовно составленных join fetch улучшило среднюю производительность в 5 раз.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406879
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пролетевший Здесь засада на уровне SQL. такой запрос возвращает строки для каждого поста со всеми категориями ( картезианское произведение ). 100 постов и 100 категорий это уже 10000 строк.
По-моему модель, в котором коллекции зачастую имеют десятки элементов и более это уже как минимум странно. Возможно даже глупо. Это всё равно что в отношении "Автомобиль - Район Регистрации" в "Районе" завести коллекцию "Автомобилей".

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

На Bag он ругался не из-за количества, а из-за того что в неупорядоченых списках он не может правильно найти нужные FK из результата запроса.

пролетевший
Больше 2х таблиц в join пихать надо с большой осторожностью.

Хотелось бы уточнить: больше двух джоинов для ассоциаций one-to-many.

пролетевший
Лучше грузить lazy с Batch Fetch .
Оффтоп, недавно настраивали производительность в приложении и обнаружили что MS SQL Join для небольшой выборки делает в несколько раз медленнее, чем 2 отдельных запроса. основная база около 10 млн записей, на каждую в среднем 20 записей в дочерних таблицах. Для обработки выбираются 4 записи из основной таблицы, ц дочерними коллекциями. Удаление любовно составленных join fetch улучшило среднюю производительность в 5 раз.
Всё верно. Спасибо за коментарий. Я сразу про это как-то не вспомнил.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406949
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczПо-моему модель, в котором коллекции зачастую имеют десятки элементов и более это уже как минимум странно. Возможно даже глупо.
Спорный вопрос как мне кажется, сущности бывают разные.
А по теме, с @OrderColumn так ничего и не вышло, к сожалению разбираться в чём проблема времени совсем нет. Проблема решилась заменой List<Category> на Set<Category>.
Огромное спасибо всем за помощь.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38406965
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SkyFireСпорный вопрос как мне кажется, сущности бывают разные.

Ну, давайте поспорим. В реальной жизни у юзера может быть сколько угодно постов. Т.е. у вас User.posts безразмерный список!
Делать join на эту коллекцию это за гранью разумного.
Даже lazy делать нужно с предельной осторожностью, потому что не факт что постраничная загрузка данных в этой коллекции будет работать. В противном случае мы отхватываем баги, когда неожиданно сервер будет уходить в OOME случайно загрузив User.posts.


SkyFireА по теме, с @OrderColumn так ничего и не вышло, к сожалению разбираться в чём проблема времени совсем нет. Проблема решилась заменой List<Category> на Set<Category>.

Да. Точно. Это второй рецепт, про который я успешно забыл.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38407017
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хорошо, вы меня переубедили :) У меня слишком мало опыта маппинге на дом-объекты да и в Java в целом.
...
Рейтинг: 0 / 0
Hibernate несколько HQL для заполнения сущности
    #38409821
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А Если написать нативный sql ?
и class RawMapper по аналогии с Jdbc подходом?!

или Вы хотите именно HQL освоить ?
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate несколько HQL для заполнения сущности
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]