【问题标题】:Pagination multiple repositories分页多个存储库
【发布时间】:2019-02-16 12:26:12
【问题描述】:

我有两个类: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 个项目。

【问题讨论】:

标签: java spring-data-jpa


【解决方案1】:

正如你提到的,计数是正确的。您需要找到一种正确显示合并数据的方法。我们可以看到您的存储库对这些类型的记录进行了排序。但是如果你将结果连接起来,它们将不会被排序。

在您的示例中,假设repoA.findAll() 返回[7,8,9]repoB.findAll() 返回[1, 100],结果[7,8,9,1,100] 将无法正确排序。您需要的解决方案取决于您的数据源(数据库)是否支持 UNION 运算符

使用联合

JPA 无法做到这一点(union operation)。但是如果您的数据库提供了union 运算符(例如:SQL 或 mongoDB),您可以使用它根据排序获取记录的 id,然后通过 JPA 按 id 获取记录。

没有工会

如果您的数据库不提供,为此,您需要创建第三个存储库,它必须从 repoA 加载 50 个项目,考虑到 aOffset,从 repoB 加载 50 个项目,考虑到 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
  }
}

【讨论】:

    猜你喜欢
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 2021-11-03
    相关资源
    最近更新 更多