oracle分頁的坑
項目用的mysql,有個需求需要連接人家的oracle。對方提供了視圖,我們這邊做了多數據源。做列表的時候分頁突然就不香了,被oracle的分頁安排的明明白白,滿滿當當!
希望我的踩坑經歷能讓更多人少走彎路,加快進度。
首先我從百度上找了一些關於oracle分頁的博客,得出oracle分頁實現代碼:
select a.* from ( select t.*,rownum rowno from test t where rownum <= 10 ) a where a.rowno >= 1
基本原理就是利用子查詢,然後傳倆參數做個分頁。本以爲如此簡單就完事了。放到項目裏成功實現了分頁,可以在我查詢第二頁第三頁的時候我發現,第一頁十條數據,第二頁變成了九條,第三頁變成了八條?越來越少,一頁更比一頁少。
debug。。。
第一頁輸出的sql:
select a.* from ( select t.*,rownum rowno from test t where rownum <= 10 ) a where a.rowno >= 1
第二頁輸出的sql:
select a.* from ( select t.*,rownum rowno from test t where rownum <= 10 ) a where a.rowno >= 2
第三頁輸出的sql:
select a.* from ( select t.*,rownum rowno from test t where rownum <= 10 ) a where a.rowno >= 3
看出來了嗎?相信寫過oracle分頁的人已經知道問題出在哪了。如果你從來沒寫過oracle分頁你一定是一臉懵逼的。
按mysql來說沒錯啊,一頁查10個,一次一頁沒問題啊??
正是慣性思維導致了這個bug,oracle和mysql不一樣。
在sql裏面rownum 和rowno 參數代表的意義並不是頁數和行數!!!!
而是開始節點和結束節點的意思!!!
rownum 是結束節點,rowno 是開始節點。以上三條sql改成如下你就明白了
#查詢第一頁的第1條到第10條
select a.* from ( select t.*,rownum rowno from test t where rownum <= 10 ) a where a.rowno >= 1
#查詢第二頁的第11條到20條
select a.* from ( select t.*,rownum rowno from test t where rownum <= 20 ) a where a.rowno >= 11
#查詢第三頁的第21條到30條
select a.* from ( select t.*,rownum rowno from test t where rownum <= 30 ) a where a.rowno >= 21
相信看到這裏,你已經恍然大悟了吧,原來如此!!!
也就是說 這兩個參數是動態傳進來的!不是死的。
我自己也寫了一個工具類提供大家參考:
public class OraclePageUtils {
public static PageDomain oraclePage(){
//PageDomain是自己項目分頁實體 不必在意
PageDomain pageDomain = TableSupport.buildPageRequest();
//關鍵在下面兩行
//oracle分頁 開始節點
//利用頁數減1 乘10 再加1 剛好就是每次開始節點的值
//比如第一頁 (1-1)*10 +1 等於 10
//比如第二頁 (2-1)*10 +1 等於 11
Integer oraclePageN = (pageDomain.getPageNum() - 1) * 10 +1;
//oracle分頁 結束節點
//利用頁數 乘 10 即爲結束節點的值
//比如第一頁 1 * 10 等於 10
//比如第二頁 2 * 10 等於 10
Integer oraclePageS = (pageDomain.getPageNum()) * 10;
//算法規則完全符合上面三條sql的實現**加粗樣式**
pageDomain.setPageNum(oraclePageN);
pageDomain.setPageSize(oraclePageS);
return pageDomain;
}
}
到這基本上Oracle分頁的這個坑就說完了,不爲別的,就爲讓別人少浪費點時間。
很欣賞馬士兵老師的一句話:如果你有一天變強了,網上有人提問,能回答儘量回答!
另外 貌似還有一個坑不知道你們是否知道?
如果你用的mybatis和pageHelper做的分頁,這個分頁插件默認的參數貌似是pageNum和pageSize。 所以如果在做oracle分頁的時候,要把這兩個參數名重寫!!重寫!!重寫!!! 寫成啥都行,不一樣就行!然後封到實體類面就行了!
希望這倆坑能幫到不少人吧!
我回去擼代碼了!今天週末還在上班!MMP!!!