分页从实现上来讲可以分为前台分页,后台分页.
前台分页就是将所有的数据一次性从数据库中读出,然后用js或java进行分页处理.这方面也有很多现成的工具可以用.比如一些js的框架或者Displaytag 标签.
这样做的优点是分页执行的动作较快,实现也比较简单.不用频繁读取数据库.缺点是如果数据库中有很多数据.假设有10w条或更多,那这些数据将占用相当多的内存和资源
你可以用你现在做的分页进行测试,看看如果你在数据库中插入10w条记录或更多,点击翻页是什么情况.
后台分页就是根据传入的参数读取部分数据.oracle 用 rownumber, sqlserver 用 top ,mysql 用 limit ,Hibernate 有设置起始值和最大值的方法,等等.这些都是为了每次访问数据库仅仅在数据库中取出一部分数据进行处理,虽然访问数据库的次数增多,但是可以避免大量的数 据被读入而占用宝贵的大量服务器资源.
如果数据量很大并且对数据库的访问效率也很在意,则考虑结合上面两种分页模式,假设库中有1000w条数据,可以先读出10页数据,然后前台分页.如过翻页到后面,则再次访问数据库进行读取。
前台分页实现
从数据库查询所有的数据,然后传到前台。前台根据选择只取其中的一页数据。
后台分页实现
后台设置每页显示的记录数,如20,然后从数据库查询20条记录,以及所有记录的总数。数据库查询语句如下:
select * from (select rownum as r, t.* from (select tableName.* from tableName ) t where rownum <= endPos) where r > startPos
对此三层嵌套分页语句我曾有两个疑惑,
第一是为什么不这样写:
select * from (select rownum as r, t.* from (select tableName.* from tableName ) t where rownum <= endPos and rownum > startPos )
因为这样得不到结果,原因是将直接编号的结果采用大于条件是没有结果的。也就是直接编号的结果不支持rownum > ..
只有将编号的结果取出再ruwnum > ..才有效,这和ORACLE的运行机制有关。
那么,为什么不这么写呢:
select * from (select rownum as r, t.* from (select tableName.* from tableName) t )where r <= endPos and r > startPos
原因是,这样没有之前的写法效率高。
第二个疑惑是将查出来的结果集rownum再取出记录,是否会导致同样的条件查到不一样的结果。比如查询rownum > 0 and rownum < 20的记录,由于每次select出来的结果集顺序有可能不一样,可能两次查询会出现不一样的结果。解决办法是在取出数据时给数据排序:
select * from (select rownum as r, s.* from (select tableName.* from tableName order by tableColum ) s ) t where rownum <= endPos) where r > startPos
为什么不这样写呢:
select * from (select rownum as r, t.* from (select tableName.* from tableName order by tableColum DESC) t where rownum <= endPos) where r > startPos
因为这样写的意思是,先给结果编号,再排序。
获得数据后,将所有数据总数与默认的第一页数据传到前台。前台会有一个JS,来根据所有数据的总数,显示有多少页,然后点其中某页时再查询数据库。