选择显示字体大小

jive中的分页处理

web应用中,难免和数据库打交道,对于返回的结果集,究竟该如何处理?
尤其是,当你的一个查询可能会返回数万条纪录的时候,你还能像某些骗钱骗精力的jsp垃圾书本上介绍的用rs.next()来处理么?
呵呵,我以前就是这么干的,直接传回resultset,在jsp中while(rs.next())循环中一个
一个的处理。

还有,返回结果的分页处理的问题。很多时候我们的web应用(或者其他)都是针对某一种数据库的(感觉商业应用绝大多数是oracle,业余的多是mysql,还敢用jdbc连接sqlserver的,估计是被m$养废了)。所以我常常会针对某些数据库的特性写一些专门的sql语句或者存储过程来确定返回结果集的大小,以实现分页处理(其实偶是数据库白痴,除了select/insert/update,其他的不知道!)。我以前就是用伪列来实现在oracle上处理记录结果集的分页的。

慢慢的,为了所谓的降低代码耦合度,我对查询结果集的代码进行了重构,于是稍微进步了一点,在某个querymanager之类的类中传出一个enumeration,里边的每个对象对应了数据库中的一条纪录。嘿嘿,居然也能凑合着对付500多人使用了。
可是,这也不是最好的办法,毕竟,如果真的返回了几万条纪录,这样的处理方法不但占内存,而且效率也不搞。

记得以前在bqlr.com中看到一篇关于“查询结果返回rs,还是集合”的讨论,答案是用iterator。
可是里边的代码很笼统,对于从未用过iterator模式的人来说,基本上没有什么可以模仿和参照的。
还好,我们有现成的,那就是jive。
看看jive中是怎么实现的。

(a)我们以forum.jsp这个页面为例,缺省的,每页显示15条thread,用户可以指定从第n条开始显示到n+page_size条。
代码如下:

resultfilter filter = new resultfilter();
filter.setstartindex(start); //从第start条thread开始
filter.setnumresults(range); //页面大小
// set the moderation level minimum
filter.setmoderationrangemin(forum.getmoderationminthreadvalue());

// more forum properties
int numthreads = forum.getthreadcount(filter);
int nummessages = forum.getmessagecount(filter);

// iterator of threads
forumthreaditerator threads = forum.threads(filter); //返回thread iterator,



通过分析上面代码,明确了需要重点分析resultfilter,dbforum和forumthreaditerator这三个类。

(b)看看resultfilter.java
这个类其实就是专门保存查询条件的,例如,可以查询某天之前,由某人发布的贴子等。一次查询操作的所有查询条件都保存在这个类里边。
里边有一个函数比较有意思:public void setsortpropertyname(string sortpropertyname),嘿嘿可以把“是否具备某个property”作为查询条件。我本来就想给jive添加thread置顶功能,看起来只要给需要置顶的thread加一个topmost属性,然后改动skin就可以了。可谓是得来全不费工夫啊。

把查询条件填充完毕以后,就可以把resultfilter传给forum.threads()取结果了。

(c)看dbforum.threads()

    public forumthreaditerator threads(resultfilter resultfilter) {
//根据传入的resultfilter构造一个查询sql语句(*注1)
        string query = getthreadlistsql(resultfilter, false);
//返回一个确定返回的id列表,这里缺省大小是400个,例如,我要看1~15条纪录
// threadblock的length是400,从1~400(*注2)
        long[]threadblock = getblock(query.tostring(), resultfilter.getstartindex());
        int startindex = resultfilter.getstartindex();
        int endindex;
        // if number of results is set to inifinite, set endindex to the total
        // number of threads in the forum.
        if (resultfilter.getnumresults() == resultfilter.null_int) {
            endindex = (int)getthreadcount(resultfilter);
        }
        else {
            endindex = resultfilter.getnumresults() + startindex;
        }
//嘿嘿,理解了上面几句代码先,然后来看这个iterator
        return new forumthreadblockiterator(threadblock, query.tostring(),
                startindex, endindex, this.id, factory);
    }


ok,关于(注1)
我分析了getthreadlistsql,这里是构造了一个sql查询语句,这个语句前面的一些内容是:
select jivethread.threadid from jivethread,xxxxx
那些xxxxx无非是一些查询条件,是根据resultfilter中的查询条件而自动生成的。
原来,如果执行了这个sql的作用只能取回满足条件的thread的id号。

(注2)getblock()
我对这里的block的理解是:指满足查询条件的查询结果经过排序以后的序号集合,和数据库中的threadid是不一样的。
这里的starindex就是数组,也就是那个block的下标,而里边的内容(long object),是真正的threadid
代码里边对于每block数组的大小,是固定的400。
举例来说:
如果一次查询返回1000条纪录,我要从第510条开始(startindex=510),那么就是取第二块block(blockid=1),块起始位置(blockstart)是
500。

int blockid = startindex / block_size;
int blockstart = blockid * block_size;



如果你还有耐性看到这里,并且接着读jive代码的话,会发现,加下来无非就是从cache中取该block数组,如果没有找到,则老老实实的从数据库中取出来,老老实实的放到数组里边,放到cache,最后扔出这个数组。
这里的数据库处理代码比较普通

con = connectionmanager.getconnection();
stmt = connectionmanager.createscrollablestatement(con);
// set the maximum number of rows to end at the end of this block.
connectionmanager.setmaxrows(stmt, block_size * (blockid+1));
resultset rs = stmt.executequery(query);
// grab block_size rows at a time.
connectionmanager.setfetchsize(rs, block_size); //一次最多取block_size条,也就是400条
// position the cursor right before the first row that we're insterested in.
connectionmanager.scrollresultset(rs, blockstart);// 滚动游标到blockstart
// keep reading results until the result set is exhausted or
// we come to the end of the block.
int count = 0;
while (rs.next() && count < block_size) {
  objectlist.add(rs.getlong(1));
  count++;
}




看到这里,我忽然领悟到,这里的代码也只是复制而已,可是比我以前的复制到enumeration中要高级了好多。
首先,这里限制了jdbc返回结果集的大小。
其次,复制的内容只是一个&ldquo;指针&rdquo;(嘿嘿,我喜欢用这个词语)。
这样就比较好的解决了上面的速度慢和浪费内存的问题。

(c)嘿嘿,接下来的事情相对就很简单了。
1.根据startindex计算出在该block中的相对位置,也就是这个blockarray中的下标啦,然后取得内容,也就是真正的threadid啦。
2.到threadcache中去取该threadobject,如果找不到,则老老实实的new thread(threadid),从数据库中去取了。
这一切都是通过forumthreaditerator中的hasnext()/next()/getelement()来实现的。大家自己去看一下就很容易搞清楚啦。



bill-转自:csdn


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons