java - 分页查询/迭代器配方

标签 java database pagination

我经常看到这种模式。

在服务器上:

// Get a bounded number of results, along with a resume token to use 
// for the next call. Successive calls yield a "weakly consistent" view of 
// the underlying set that may or may not reflect concurrent updates.
public<T> String getObjects(
        int maxObjects, String resumeToken, List<T> objectsToReturn);

在客户端:

// An iterator wrapping repeated calls to getObjects(bufferSize, ...)
public<T> Iterator<T> getIterator(int bufferSize);

大多数地方都推出了这两种方法的自己的版本,而且实现起来非常困难。有很多边缘案例错误。

这些查询是否有规范的方法或库?

(您可以对服务器端存储做一些简化假设,例如 T 具有自然顺序)。

最佳答案

这是对我有用的东西。它还使用来自 google-guava 库的 AbstractIterator,但利用 Java8 Stream 来简化实现。它返回类型为 T 的元素的迭代器。

Iterator<List<T>> pagingIterator = new AbstractIterator<List<T>>() {
    private String resumeToken;
    private boolean endOfData;

    @Override
    protected List<T> computeNext() {
        if (endOfData) {
            return endOfData();
        }

        List<T> rows = executeQuery(resumeToken, PAGE_SIZE);

        if (rows.isEmpty()) {
            return endOfData();
        } else if (rows.size() < PAGE_SIZE) {
            endOfData = true;
        } else {
            resumeToken = getResumeToken(rows.get(PAGE_SIZE - 1));
        }

        return rows;
    }
};

// flatten Iterator of lists to a stream of single elements
Stream<T> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(pagingIterator, 0), false)
    .flatMap(List::stream);

// convert stream to Iterator<T>
return stream.iterator();

也可以通过以下方式使用方法引用返回一个 Iterable:

// convert stream to Iterable<T>
return stream::iterator;

关于java - 分页查询/迭代器配方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12557837/

相关文章:

mysql - BASH Mysql输出语句的一部分

php - 有没有更好的方法来编写这个 MySQL 查询?

mysql - 分页和表单标签问题

php - $_GET 变量在分页代码中未定义

java - 如何为 Java 应用程序创建安装程序?

java - Spring Boot 验证信息未显示在 Swagger UI 中

java - 如何在 Banjo 中为变量设置任意数量的值

mysql - 不确定如何设计有条件的一对多关系

java - 在 Spring 存储库中获取可分页自定义查询的总行数

java - 没有最大小数位数的 NumberFormat