3

我在以下设计中需要帮助。我公开了一个SQL select从数据库执行的 Web 方法。问题是记录的数量可能很大,我不想在一次调用中返回所有记录。
所以我可以想到这些选项(在页面中返回结果):
1)提供一个带参数的方法,以便客户端recordStart每次recordEnd请求。
2)修改方法以接受大小的结果集,X并以某种方式理解每个请求不是新请求而是返回下一个X记录。为了弄清楚每个客户端可以关联某种令牌,但问题是我不确定该令牌应该保留多长时间然后处理,以便将传入请求视为第一个请求或前一个请求的延续一。

那么我应该选择哪种设计,我将如何解决我提到的任何相关问题?
有没有更好的方法来处理这些问题?

4

3 回答 3

2

从我的角度来看:

  • 每个请求都可以封装在一个请求对象中,该对象基本上包含一个偏移量和一个页面大小;
  • 每个响应都可以封装在一个响应对象中,该对象基本上会有一个结果列表和一个总数,或者您可以保存用于构建响应的请求对象;

您在数据库上执行选择的界面将类似于:

public PageResponse getPage(PageRequest pageRequest);

这种方法很容易扩展你的分页方法,想象在几个月后你需要对那个方法实现一个排序,你需要改变对它的每次调用。使用这种方法,您可以更改PageRequest对象并提供默认排序,不会破坏任何内容,您可以仅在真正需要它的调用中自定义排序。

在此方法中,您将需要两个不同的数据库选择:

  • 一个是为了检索选择列表(将由响应保存并通过属性 resultList 访问的列表),这可以使用每个数据库的特定功能来限制您的结果集(top对于 sybase,limit对于 mysql 和 PG,rownum对于 Oracle,这将因一个数据库而异);
  • 另一种是在不分页的情况下获取所选记录的总数,以便在大数据集的情况下对数据执行分页。

您的问题的一个很好的参考是Spring Data,它们有PagePageRequest这或多或少是您需要的。也许您可以使用他们的 API 来实现您的解决方案。


实际上,您的请求对象可能如下所示:

public class PageRequest {

    private int offset;
    private int pageSize;

    // getters and setters and convenience constructors with the given fields

}

public class PageResponse {

    private List<?> resultList;
    private int total;

    // getters and setters and convenience constructors with the given fields

}

当然,您也可以使用泛型来获得您已经请求的响应保存类型,从而促进响应对象的使用,例如:

public <T> PageResponse<T> getPage(PageRequest<T> pageRequest);

具有 Request 和 Response 的对象,例如:

public class PageRequest<T> {

    private int offset;
    private int pageSize;

    // getters and setters and convenience constructors with the given fields

}

public class PageResponse<T> {

    private List<T> resultList;
    private int total;

    // getters and setters and convenience constructors with the given fields

}
于 2012-08-01T06:45:03.257 回答
0

更好的方法和最广泛使用的是1).

在这种情况下,sql过程和客户端代码之间没有约束(就像OOP中根据接口编程一样)。

然后查看令牌所在的哈希值也很简单且不易出错,因此您可以获取当前位置。您还必须在某处记住这个散列(内存用于速度或磁盘用于持久性)。

如您所见,这种方法很复杂,如果您深入思考它,您必须做出比第一种方法更多的决定。

此外,第一种方法在设计应用程序 b/c 时为您提供了更多自由,它的行为类似于 OOP 封装。将来,您还可以使用另一段代码为您记住当前位置,客户端将调用此代码,然后此代码将调用数据库将结果传递给客户端。

底线,去1)

于 2012-08-01T06:44:17.810 回答
0

如果您想返回结果总数,我会选择两种选项的组合:

  • 新查询(未给出标识符):
    • 首先在没有 order by 子句的情况下对整个结果集(select count(*) from ...)进行行计数。
    • 如果结果集真的太大,您可以在此处返回错误 [可选]
    • 获取页面数据(排序是强制性的,由您或您的 api 用户定义)
    • 生成一个标识符并将其与结果计数[以及可选的查询]一起保存
    • 返回页面数据、总结果计数和查询标识符
  • 下一个查询(给定标识符):
    • 获取持久化结果计数
    • 获取页面数据(排序是强制性的,由您或您的 api 用户定义)
    • 返回页面数据、总结果计数和查询标识符

最好的办法是将查询(没有分页部分)与标识符一起保留,这样您甚至不必在下次调用时再次创建它。

于 2012-08-01T09:09:32.327 回答