如何在页面/部件中最好地返回SQL结果

时间:2012-08-01 06:35:25

标签: java sql database design-patterns

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

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

3 个答案:

答案 0 :(得分: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

}

当然,您也可以使用Generics,以便拥有您已经请求的响应保持类型,以便于使用响应对象,如:

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

具有请求和响应的对象,如:

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

}

答案 1 :(得分:0)

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

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

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

正如你所看到的,这种方法很复杂,如果你仔细思考它,你必须做出比第一种方法更多的决定。

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

最后一行,请使用1)

答案 2 :(得分:0)

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

  • 新查询(未给出标识符):
    • 首先在没有order by子句的情况下对完整结果集(从...中选择count(*))进行行计数。
    • 如果结果集太大[可选]
    • ,您可能会返回错误
    • 获取页面数据(必须由您或您的api用户定义)
    • 生成一个标识符并将其与结果计数[以及可选的查询]
    • 一起保留
    • 返回页面数据,总结果计数和查询标识符
  • 下一个查询(给定标识符):
    • 获取持久结果计数
    • 获取页面数据(必须由您或您的api用户定义)
    • 返回页面数据,总结果计数和查询标识符

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