Page <> vs Slice <>何时使用哪个?

Emi*_*ski 11 java spring spring-data spring-data-jpa

我在Spring Jpa Data 文档中阅读了关于两个不同类型的对象的信息,这些文档是在您对存储库进行动态查询时进行的.

页面切片

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

Slice<User> findByLastname(String lastname, Pageable pageable); 
Run Code Online (Sandbox Code Playgroud)

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

有没有人有这种类型的知识,文章或一些好的信息来源?

cas*_*lin 13

PageSlice通过触发计数查询来扩展并了解可用的元素和页面总数.从Spring Data JPA 文档:

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

  • 是的,我已经读过了.我想知道差异是否大于那个,但我认为不是.这个答案似乎已经足够了:)感谢所有人 (2认同)

Pra*_*ran 8

Slice和之间的主要区别Page在于,后者提供了满足查询条件的重要分页详细信息,例如记录总数 ( getTotalElements())、总页数 ( getTotalPages()) 和下一页可用性状态 ( hasNext()) ,另一方面,前者仅提供分页详细信息,例如hasNext()与其对应项相比的下一页可用性状态( ) PageSlice当您处理包含不断增长的记录的庞大表时,可提供显着的性能优势。

让我们更深入地研究这两个变体的技术实现。

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());
    }
}

Run Code Online (Sandbox Code Playgroud)

如果您观察上面的代码片段,PagedExecution#doExecute 方法底层会调用 PagedExecution#count 方法来获取满足条件的记录总数。

    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);

    }
}

Run Code Online (Sandbox Code Playgroud)

如果您观察上面的代码片段,为了查明下一组结果是否存在(对于hasNext()),该SlicedExecution#doExecute方法总是获取额外的一个元素(createQuery.setMaxResults(pageSize + 1))并根据 pageSize 条件跳过它(hasNext ? resultList.subList(0, pageSize) : resultList)。

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

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