Hibernate ScrollableResults не возвращает весь набор результатов - PullRequest
2 голосов
/ 05 апреля 2010

Некоторые из выполняемых нами запросов имеют более 100 000 результатов, и их загрузка занимает много времени, а затем отправляется клиенту. Поэтому я использую ScrollableResults, чтобы иметь функцию постраничных результатов. Но мы достигаем примерно 50 000 результатов (никогда не бывает одинакового количества результатов).

Я нахожусь в базе данных Oracle9i, использую драйверы Oracle 10, а Hibernate настроен на использование диалекта Oracle9. Я попытался использовать последнюю версию драйвера JDBC (ojdbc6.jar), и проблема была воспроизведена.

Мы также следовали некоторым советам и добавили пункт заказа, но проблема была воспроизведена.

Вот фрагмент кода, который иллюстрирует, что мы делаем:

final int pageSize = 50;
Criteria crit = sess.createCriteria(ABC.class);
crit.add(Restrictions.eq("property", value));
crit.setFetchSize(pageSize);
crit.addOrder(Order.asc("property"));
ScrollableResults sr = crit.scroll();
...
...
ArrayList page = new ArrayList(pageSize);
do{
  for (Object entry : page)
    sess.evict(entry); //to avoid having our memory just explode out of proportion
  page.clear();
  for (int i =0 ; i < pageSize && ! metLastRow;  i++){
    if (sr.next())
      page.add(sr.get(0));
    else 
      metLastRow = true;
  }
  metLastRow = metLastRow?metLastRow:sr.isLast();

  sendToClient(page);
}while(!metLastRow);

Итак, почему я получаю набор результатов, чтобы сообщить мне его в конце, когда у него должно быть намного больше результатов?

Ответы [ 2 ]

1 голос
/ 05 апреля 2010

В вашем фрагменте кода отсутствуют важные фрагменты, такие как определения resultSet и page. Но мне все равно интересно, разве линия не должна

if (resultSet.next())

будь скорее

if (sr.next())

В качестве примечания, AFAIK, очищающий лишние объекты от контекста постоянства, может быть достигнут простым вызовом

session.flush();
session.clear();

вместо циклического перебора коллекции объектов для выселения каждого отдельно. (Конечно, для этого требуется, чтобы запрос выполнялся в своем независимом сеансе.)

Обновление: ОК, следующий раунд догадок: -)

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

Еще одна вещь, которую вы можете попробовать это

crit.setFirstResults(0).setMaxResults(200000);
0 голосов
/ 01 апреля 2014

Поскольку у меня была та же проблема с большим кодом проекта, основанным на List<E> экземплярах, Я написал действительно ограниченную реализацию List с поддержкой только итераторов для просмотра ScrollableResults без рефакторинга всех реализаций служб и прототипов методов.

Эта реализация доступна в моем IterableListScrollableResults.java Gist

Он также регулярно сбрасывает сущности Hibernate из сессии. Вот способ его использования, например, при экспорте всех неархивированных объектов из БД в виде текстового файла с циклом for:

Criteria criteria = getCurrentSession().createCriteria(LargeVolumeEntity.class);
criteria.add(Restrictions.eq("archived", Boolean.FALSE));
criteria.setReadOnly(true);
criteria.setCacheable(false);
List<E> result = new IterableListScrollableResults<E>(getCurrentSession(),
        criteria.scroll(ScrollMode.FORWARD_ONLY));
for(E entity : result) {
    dumpEntity(file, entity);
}

С надеждой, что это может помочь

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