2012-04-18 2 views
5

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

Следует также упомянуть, что я хочу присоединиться к нему в другую таблицу под названием 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. Я получаю эту ошибку:

Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list

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

ответ

1

Этот код из 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() + "]" 
         ); 

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

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

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

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

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

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

+0

Я думаю, что этот ответ правильный. Если это так, вы должны позволить Hibernate знать, что вы действительно выбираете 'Item', меняя запрос, чтобы возвращать' List', а не создавать 'Order':' select i, p from ... '. Затем вам нужно будет создать «Заказ вручную». –

0

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

Смежные вопросы