老声常谈,分页查询的实现就是不分页

05-11-11 cats_tiger
分页查询是经常遇到的问题,几乎每个项目都会遇到,如此常见的问题,我们的数据库却没有提供现成的解决方法,例如Oracle提供Rownum字段,SQLServer提供TOP关键字,MySQL提供Limit关键字。Hibernate作为常用的ORM方案,也没提供一个类似pageQuery之类的方法。他们都提供了分页查询的途径却没有提供分页查询的直接实现。为什么呢。
其实无论是TOP还是setMaxResults,都不是用于分页查询的,他们的目的在于通过限制抓取数量来提高查询性能,Rownum也是如此,这就是为什么Rownum在OrderBy之后就乱的原因(Oracle完全有能力让它OrderBy之后仍然有序)。那么我们怎么还要分页查询呢?无非是两个原因,其一是提高性能,其二是方便用户使用――没有哪个用户会关心1000行之外的数据。
这样就简单了,我们不必费心如何高效而优雅的从数据库中抓取某一页数据,而是在查询出所有数据(在maxResults限制下)之后,在内存中分页。例如,List getUsers()获取前1000个用户――对于企业应用,这已经很多了――在返回的List中作分页,即高效又简单,而且如果加入缓存机制之后,就不必每次翻页都重新查询了。
下面是示意类图:

cats_tigeresV5bl0fFs.JPG

xl44
2005-11-11 14:53
我以前的公司一直是这么做的,已经用了好多年了.这样的好处就是可以写一个通用的分页tag出来,而且框架可以适用所有数据库,等到开发的时候做分页就很容易了.最大查询数在配置文件定义,一般定义在3000-5000,但现在的hibernate不知道有没有这种功能,不然要自己写sql了

cats_tiger
2005-11-13 09:40
Hibernate有,可以设置setMaxResults。
如果做一层缓存会怎样呢,比如这个方法:
List getPage(String sql, Object[]params,int pageNo,int pageSize)
可以缓存包含所有结果的List,然后分页,下次查询的时候根据条件取回List即可。

yuxie
2005-11-14 08:47
我无语……
各位的公司都比较强……

banq
2005-11-14 15:33
>是在查询出所有数据(在maxResults限制下)之后,在内存中分页。

实践证明,这种方法虽然简单,但是非常耗费内存,scalable不行。肆无忌惮 急剧使用内存,会遭受JVM报复的。

纽国群
2005-11-16 13:42
哈哈其实2中方法各有利弊,
第一中,是把数据读出来放到内存中,(比较站用内存资源)
第2中,是每次分页都要读取数据库,晕
不过我还是比较喜欢用 2

猜你喜欢