Пагинация нескольких репозиториев - PullRequest
0 голосов
/ 16 февраля 2019

У меня есть два класса: A, B. Для каждого класса у меня есть хранилище.Я хочу отображать данные в одной таблице (внешний интерфейс, что-то похожее на: http://embed.plnkr.co/V06RsBy4a6fShwmZcUEF/). Я хочу иметь нумерацию страниц на стороне сервера.

List<Object> result = new ArrayList();
result.addAll(repoA.findAll());
result.addAll(repoB.findAll());

public interface repoAPaginationRepository extends PagingAndSortingRepository<A, Long> {
    Page<A> findAll(Pageable pageRequest);
}

public interface repoAPaginationRepository extends PagingAndSortingRepository<B, Long> {
    Page<B> findAll(Pageable pageRequest);
}

Достаточно ли суммировать "количество" из обоих репозиториев?Пример: Репозиторий A: 100 элементов, Репозиторий B: 50 элементов. Сумма: 150 элементов. Я хочу отобразить 50 элементов на странице.

1 Ответ

0 голосов
/ 16 февраля 2019

Как вы упомянули, счет будет правильным.вам нужно найти способ правильно отобразить объединенные данные.Мы видим, что ваши репозитории сортируют записи среди этих типов.Но если вы объедините результаты, они не будут отсортированы.

В вашем примере предположим, что repoA.findAll() return [7,8,9] и repoB.findAll() return [1, 100], результат [7,8,9,1,100] не будетотсортировано правильно.Решение, которое вам нужно, зависит от того, поддерживает ли ваш источник данных (База данных) оператор UNION или нет

Использование объединений

JPA не может сделать это (операция объединения) .Но если в вашей базе данных есть оператор union (например, SQL или mongoDB), вы можете использовать его для извлечения идентификаторов записей в соответствии с сортировкой, а затем извлекать записи по идентификаторам через JPA.

Нет объединений

Если ваша база данных не предоставляет, для этого вам потребуется создать третий репозиторий, он должен загрузить 50 элементов из repoA с учетом aOffset и 50 элементов с repoB с учетомbOffset, затем сортируйте 100 из них (это должно быть быстро с сортировкой слиянием, и вы можете остановить алгоритм на 50).

Код будет выглядеть примерно так

interface RepoA {
  List paginate(int count, int offset, SortCriteria sortCriteria);
}

interface RepoB {
 List paginate(int count, int offset, SortCriteria sortCriteria);
}

class RepoAB {
  private RepoA repoA;
  private repoB repoB;


  List paginate (int count, int offset, SortCriteria sortCriteria) {
     int aOffset = count == 0 ? 0 : calcAOffset(offset, sortCriteria);
     int bOffset = count == 0 ? 0 : offset - aOffset;
     return mergeSort(
             repoA.paginate(count, aOffset),
             repoB.paginate(count, bOffset),
             SortCriteria sortCriteria,
             50
           )
  }

  List mergeSort(List aList, List bList, SortCriteria sortCriteia, int stopAt) {
    ...
  }

  int calcAOffset (int offset, SortCriteria sortCriteria) {
    // This implementation can be very heavy, it will count all the records that
    // that appeared in the previous pages. 
    // You can evade this computation by knowing the offset using the last record 
    // in the previous page.
    return paginate(offset, 0, sortCriteria).filter(x => x instanceOf A).length
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...