Стремитесь извлекать коллекции в Hibernate с ScrollableResults

Я пытаюсь использовать Hibernate для извлечения примерно 100 миллионов строк из таблицы. У меня есть постоянный объект сущности, который содержит коллекцию сборов внутри (еще один постоянный объект). Учитывая, что я буду перебирать результат и получать доступ к плате за каждый объект, я хочу охотно получать комиссию, чтобы избежать проблемы n+1.

Я должен также упомянуть, что я хочу присоединить его к другой таблице с именем Provider (сопоставление "один к одному", но без внешнего ключа). Я старался:

String query = "select new " + Order.class.getName() 
           + "(i, p) from Item i left join fetch i.fees f, Provider p where "
           + "p.factoryId=i.factoryId and p.factoryRef=i.factoryRef";

return session.createQuery(query).scroll();

Класс My Order содержит поле Provider и поле Item. Я получаю эту ошибку:

Вызвано: org.hibernate.QueryException: в запросе указано объединение выборки, но владелец извлеченной ассоциации не присутствовал в списке выбора

Я хотел бы закончить с прокручиваемым списком Заказа, который содержит Предмет (с уплатой сборов) и Провайдера.

2 ответа

Решение

Этот код из SelectClause причиняет вам неприятности:

if ( !fromElementsForLoad.contains( origin ) ) {
                        throw new QueryException(
                                "query specified join fetching, but the owner " +
                                "of the fetched association was not present in the select list " +
                                "[" + fromElement.getDisplayText() + "]"
                        );

Как вы можете видеть, когда упомянуто ключевое слово fetch, hibernate проверяет, просили ли вы указать родительское поле с украшенными выборками. fromElementsForLoad.contains( origin )

Вероятно, они сделали это, чтобы защитить вас от создания избыточного соединения, которое будет стоить вам очень дорого. Это хорошая вещь, потому что нет причин для извлечения ассоциации, если вы никогда не используете ее.

Я считаю, что в вашем случае - упаковка Item.class в новом Order.class скрывает тот факт, что вы используете в запросе родительское поле с оформленными выборками.

У меня нет отладочных способностей, поэтому я не могу это проверить. попытайтесь отладить эту точную строку из SelectClause.class и посмотрите, какие элементы fromElementsForLoad коллекция держит.

Если вы хотите избежать проблемы n+1, я бы рекомендовал инициализировать класс Order.class после запроса. Вы можете выбрать только пункт и поставщика.

Если вы не можете проверить это, я найду подходящий компьютер на следующей неделе и расширю свой ответ.

Попробуйте удалить left join fetch i.fees f и сделайте нетерпеливое извлечение в отображении.

Другие вопросы по тегам