<script type="text/javascript"> </script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> | ||||
在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,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條紀錄
//嘿嘿,理解了上面幾句代碼先,然後來看這個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。
如果你還有耐性看到這裡,並且接著讀jive代碼的話,會發現,加下來無非就是從Cache中取該Block數組,如果沒有找到,則老老實實的從數據庫中取出來,老老實實的放到數組裡邊,放到Cache,最後扔出這個數組。 這裡的數據庫處理代碼比較普通
看到這裡,我忽然領悟到,這裡的代碼也只是複製而已,可是比我以前的複製到enumeration中要高級了好多。 首先,這裡限制了jdbc返回結果集的大小。 其次,複製的內容只是一個「指針」(嘿嘿,我喜歡用這個詞語)。 這樣就比較好的解決了上面的速度慢和浪費內存的問題。 (C)嘿嘿,接下來的事情相對就很簡單了。 1.根據startIndex計算出在該Block中的相對位置,也就是這個BlockArray中的下標啦,然後取得內容,也就是真正的threadID啦。 2.到threadCache中去取該threadObject,如果找不到,則老老實實的new thread(threadID),從數據庫中去取了。 這一切都是通過ForumThreadIterator中的hasNext()/next()/getElement()來實現的。大家自己去看一下就很容易搞清楚啦。 bill-轉自:csdn |
Jive中的分頁處理
最新推荐文章于 2025-04-11 11:00:30 发布