2012-08-01 87 views
3

我需要以下设计方面的帮助。我公开了一种从数据库执行SQL select的Web方法。问题是记录的数量可能很大,我不想在一次调用中返回所有记录。
所以我可以想到这些选项(以页面形式返回结果):
1)提供一个参数方法,以便客户端每次请求recordStartrecordEnd
2)修改该方法以接受大小为X的结果集,并以某种方式理解每个请求不是新的请求,而是返回下一个X记录。为了解决这个问题,每个客户端都可以关联一些令牌,但问题是我不确定这个令牌应该保存多久,然后处理一个传入的请求,作为第一个请求或之前的延续一。如何最好地返回页面/零件中的SQL结果

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

回答

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 

} 

你当然可以也才能有你已经要求回答保持类型打了一下泛型,便于使用Response对象一样的:

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 

} 
+0

不错的aproach.I想知道,这种类型的API是不是向客户端公开了大量的SQL层细节? – Jim 2012-08-02 06:18:32

+0

这取决于你如何实现它。但是没有SQL细节会暴露出来,'PageRequest'会将参数保存为常规的java对象。 – 2012-08-02 06:44:44

0

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

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

然后,查看令牌所在的散列,它也很简单并且不易出错,因此您可以获取当前位置。你也必须在某处记住这个散列(内存速度或磁盘耐久性)。如你所见,这种方法很复杂,如果你深入思考,你必须做出更多的决定,然后才是第一种方法。

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

0

如果要返回结果的总数,我会去的这两个选项的组合:

  • 新查询(无标识):
    • 首先要做的行数完整的结果集(从...中选择count(*)),不包含order by子句。
    • 这里如果ResultSet实在是太大了,你可能会返回一个错误[可选]
    • 获取页面的数据(排序是强制性的,要么定义您或您的API的用户)
    • 生成一个标识符和坚持它与结果计数[以及可选的查询]查询
    • 返回页面数据,总的结果计数和标识符
  • 接着查询(标识符给出):
    • 获取持久资源ULT数
    • 获取页面的数据(排序是强制性的,无论是由您或您的API的用户自定义)
    • 返回页面数据,查询的总结果数和标识

的最好的做法是将查询(不带分页部分)和标识符一起保存,这样你就不用再次调用下一次调用时再创建它。

相关问题