利用存儲過程進行分頁
-
在開發中我們經常以列表的方式進行數據的訪問,當訪問的數據量非常的大的時候
我們就要進行分頁,其中的一種方式就是利用存儲過程進行分頁。
環境:netbeans7.1 ,jdk 1.7 ,sqlserver 2008,tomcat 7
1. 存儲過程的編寫:
CREATE PROCEDUREproduce
@sqlstrnvarchar(4000),--查詢字符串
@currentpageint,--第N頁
@pagesizeint--每頁行數
AS
BEGIN
SETNOCOUNTON;
declare--聲明變量
@P1int,-- 遊標的ID
@rowcountint,--總行記錄
@totalpageint--總頁數
execsp_cursoropen@P1output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcountoutput
set@totalpage=CEILING(1.0*@rowcount/@pagesize)--計算總頁數
select@currentpageascurrpage,@totalpageastotalpage,@rowcountastotalrow--查出需要的值
if@currentpage>@totalpageset@currentpage=@totalpage--當前頁碼不能大於總頁數
set@currentpage=(@currentpage-1)*@pagesize+1
execsp_cursorfetch@P1,16,@currentpage,@pagesize
execsp_cursorclose@P1
setnocountoff
END
系統參數說明:
/**
sp_cursoropen:
系統參數,打開遊標。sp_cursoropen定義與遊標和遊標選項相關聯的SQL 語句,然後填充遊標。
sp_cursoropen等效於Transact-SQL 語句DECLARE_CURSOR 和OPEN 的組合。
此過程通過在表格格式數據流(TDS) 數據包中指定ID = 2 來調用。
參數說明:
cursor:@P1 遊標id SQL Server 生成的遊標標識符cursor 是一個具有int返回值的必需參數。
stmt:@sqlstr定義遊標結果集的必需參數
scrollopt:@scrollopt滾動選項。scrollopt是一個可選參數.需要int輸入值 0x0001 對應KEYSET
ccopt:@ccopt併發控制項0x0001 對應READ_ONLY
rowcount:@rowcount要用於AUTO_FETCH 的提取緩衝區行數。默認值爲20 行。
**/
/**
sp_cursorfetch:
從數據庫中提取由一行或多行組成的緩衝區。此緩衝區中的行組稱爲遊標的“提取緩衝區”。可通過在表格格式數據流(TDS) 包中指定ID = 7 來調用sp_cursorfetch。
參數說明:
cursor:@P1 遊標的ID
fetchtype : 16
rownum: @currentpage
nrows :@pagesize
**/
/**
sp_cursorclose:
關閉遊標並取消遊標分配,以及釋放所有關聯資源;
**/
Java代碼:
package Service;
importjava.sql.*;
public class Procedure {
private Connection con;
publicResultSetrs;
privateCallableStatementcallsta;
private String use = "sa";
private String pwd = "123";
public Procedure() {
try {
// 連接數據庫驅動
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String str = "jdbc:sqlserver://localhost:1433;databasename=tutorial";
con = DriverManager.getConnection(str, use, pwd);
// 設置存儲過程參數
String st = "{call produce(?,?,?)}";
callsta = con.prepareCall(st);
callsta.setString(1, "select * from product");
callsta.setInt(2, 1);
callsta.setInt(3, 3);
// 循環輸出調用存儲過程的記錄結果
StringBuffersb=new StringBuffer();
intrsNum=0;//統計結果集的數量
intupdateCount = -1;
boolean flag = callsta.execute();// 這個而爾值只說明第一個返回內容是更新計數還是結果集。
do {
updateCount = callsta.getUpdateCount();
if (updateCount != -1) {// 說明當前行是一個更新計數
// 處理.
System.out.println("..說明當前行是一個更新計數..");
callsta.getMoreResults();
continue;// 已經是更新計數了,處理完成後應該移動到下一行
// 不再判斷是否是ResultSet
}
rs = callsta.getResultSet();
if (rs != null) {// 如果到了這裏,說明updateCount == -1
// 處理rs
rsNum++;
System.out.println("統計結果集的數量:"+rsNum);
if (rs != null) {
ResultSetMetaDatarsmd = rs.getMetaData(); // 獲取字段名
intnumberOfColumns = rsmd.getColumnCount(); // 獲取字段數
inti = 0;
while (rs.next()) { // 將查詢結果取出
for (i = 1; i<= numberOfColumns; i++) {
// System.out.println(rs.getInt("總頁數"));
String date = rs.getString(i);
sb.append(date+" ");
}
}
rs.close();
}
callsta.getMoreResults();
continue;
// 是結果集,處理完成後應該移動到下一行
}
// 如果到了這裏,說明updateCount == -1 &&rs == null,什麼也沒的了
System.out.println(sb.toString());
} while (!(updateCount == -1 &&rs == null));
// callsta.getXXX(int);//獲取輸出參數
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] age) {
Procedure pro = new Procedure();
}
}