页面<> vs Slice<>什么时候用哪个?

时间:2018-04-19 10:37:24

标签: java spring spring-data spring-data-jpa

我在Spring Jpa Data documentation中读到了关于两个不同类型的对象的信息,当您“寻找”由存储库创建的动态查询时。

页面切片

Page<User> findByLastname(String lastname, Pageable pageable);

Slice<User> findByLastname(String lastname, Pageable pageable); 

所以,我试图找到一些文章或任何关于两者的主要差异和不同的用法表现如何变化以及如何排序支持两种类型的查询。

是否有人拥有此类知识,文章或一些良好的信息来源?

2 个答案:

答案 0 :(得分:10)

Page扩展Slice并通过触发计数查询来了解可用的元素和页面总数。来自Spring Data JPA documentation

  

Page知道可用元素和页面的总数。它通过基础设施触发计数查询来计算总数来实现。由于这可能很昂贵,具体取决于所使用的商店,Slice可以用作返回。 Slice只知道是否有可用的下一个Slice,这在浏览更大的结果集时可能就足够了。

答案 1 :(得分:0)

SlicePage之间的主要区别在于,后者提供了重要的分页详细信息,例如记录总数(getTotalElements()),页面总数({{1} })和满足查询条件的下一页可用性状态(getTotalPages()),另一方面,前者仅提供分页详细信息,例如下一页可用性状态(hasNext()hasNext()。当您处理具有庞大记录的庞大表时,Page可以显着提高性能。

让我们深入研究两种变体的技术实现。

Slice

如果您观察到以上代码片段,则PagedExecution#doExecute方法会从根本上调用PagedExecution#count方法来获取满足条件的记录总数。

static class PagedExecution extends JpaQueryExecution {
    @Override
    protected Object doExecute(final AbstractJpaQuery repositoryQuery, JpaParametersParameterAccessor accessor) {

        Query query = repositoryQuery.createQuery(accessor);
        return PageableExecutionUtils.getPage(query.getResultList(), accessor.getPageable(),
                () -> count(repositoryQuery, accessor));
    }

    private long count(AbstractJpaQuery repositoryQuery, JpaParametersParameterAccessor accessor) {

        List<?> totals = repositoryQuery.createCountQuery(accessor).getResultList();
        return (totals.size() == 1 ? CONVERSION_SERVICE.convert(totals.get(0), Long.class) : totals.size());
    }
}

如果您观察上述代码片段,则要找出是否存在下一组结果(对于 static class SlicedExecution extends JpaQueryExecution { @Override protected Object doExecute(AbstractJpaQuery query, JpaParametersParameterAccessor accessor) { Pageable pageable = accessor.getPageable(); Query createQuery = query.createQuery(accessor); int pageSize = 0; if (pageable.isPaged()) { pageSize = pageable.getPageSize(); createQuery.setMaxResults(pageSize + 1); } List<Object> resultList = createQuery.getResultList(); boolean hasNext = pageable.isPaged() && resultList.size() > pageSize; return new SliceImpl<>(hasNext ? resultList.subList(0, pageSize) : resultList, pageable, hasNext); } } ),hasNext()方法总是获取一个元素(SlicedExecution#doExecute)并跳过它基于pageSize条件(createQuery.setMaxResults(pageSize + 1))。

  • 应用程序:
    • 页面

      当UI / GUI希望在搜索/查询本身的初始阶段显示所有结果时,使用要遍历的页码(例如,具有页码的bankStatement)时使用

    • 切片

      当UI / GUI期望在搜索/查询本身的初始阶段不希望显示所有结果但打算根据滚动或下一个按钮单击事件显示要遍历的记录(例如,Facebook feed)时使用搜索)