mysql中用存儲過程做分頁操作

在數據庫中有一個很重要的查詢,叫分頁查詢,因爲每每可能做查詢操作時符合查詢條件的數據太多,導致無法全部顯示在一個頁面上,不方便瀏覽,所以便想把數據一頁一頁的分別顯示,由此,便產生了分頁查詢這個操作。做一個對某個具體表的簡單的分頁查詢很簡單,只需在select語句的最後加上limit  currentPage,PageSize即可,那麼,如何做對任意一個表的分頁查詢呢,今天,我便來和大家講一講如何做一個通用的分頁查詢工具,即可用任意的查詢條件,任意的排序列和排序類型來對任意表的任意的列進行查詢。

本文章分爲兩部分:

1、存儲過程部分:在mysql數據庫中用存儲過程做分頁操作

2、jdbc中執行存儲過程:在java中用jdbc連接數據庫執行帶輸出參數的存儲過程

一、存儲過程部分

用任意的查詢條件,任意的排序列和排序類型來對任意表的任意的列進行查詢,則輸入參數必須要有表名稱,要查詢的列名稱(或者列名稱的列表),查詢條件,排序列的名稱,排序的排序類型(降序desc或升序asc),另外,還需傳入需要顯示的當前頁的頁數和每頁的大小(即每頁需要顯示的數據條數),也可通過該查詢的存儲過程傳出查詢得到的數據總條數和總頁數。

CREATE procedure pro_page2(
vtable_name varchar(20), 	#任意表   必填
vclumn_name varchar(30),	#任意的查詢列 可選	
vtiaojian varchar(50),		#任意查詢條件 可選
sortcolumn varchar(20),		#任意的排序列 可選
sorttype varchar(4),			#任意的排序類型(asc,DESC) 可選
currentPage int,					#當前頁碼 必填
recordNum int,						#頁面大小 必填
out countPage int,				#符合條件數據的總頁數
out countNum int)					#符合條件的數據的總條數

寫好了存儲過程頭部的參數準備部分,就要正式做查詢了,不過,在查詢之前,先要對傳入的參數進行預處理,在輸入參數中表名稱,當前頁的頁數和每頁的大小爲必須傳入的查詢參數,而要查詢的列名稱,查詢條件,排序列的名稱,排序的排序類型則爲可選的輸入參數,即可傳入具體的值,也可爲null值。

查詢列爲空時,則默認爲對所有的列進行查詢,即其值可爲" * " ,查詢條件爲空時,則默認爲對所有的數據進行查詢,即其值可爲恆成立的" 1=1 ",排序列爲空時,則可默認爲按主鍵即按每個表的id列進行排序,排序類型爲空時,可默認爲按降序排序。

BEGIN
#設置查詢的起始位置
declare startNum int;

#判斷是否填寫查詢列,查詢條件,排序列,排序類型
if vclumn_name is null or vclumn_name = '' THEN
	set vclumn_name='*';
end if;
#判斷是否填寫查詢條件
if vtiaojian is null or vtiaojian='' then 
	set vtiaojian = '1=1';
end if;
#判斷是否填寫排序列,若未填寫則使用默認的排序列“_id”,需要事先約定好
if sortcolumn is null or sortcolumn = '' THEN
	set sortcolumn = '_id';
end if;
#判斷是否填寫排序類型,若未給定或者不符合要求,則默認使用升序(ASC)
if lower(sorttype) <> 'asc' and lower(sorttype) <> 'desc' then
	set sorttype = 'asc';
end if;

要把這些參數都用到select 語句中,不能直接將查詢語句寫成select  clumn_name  from tablb_name  where  limit     ,這樣的話,字符串" tablb_name "會被當做是一個表的表名,字符串"clumn_name"會被當做是tablb_name這個表中的某一個列的列名,其餘的參數也是如此,不是將參數傳入select語句中,而是取其字面的意思。所以,要將參數傳入select語句中,需用concat()函數對select語句進行連接,然後對sql語句進行預編譯,再執行其預處理對象。

set startNum=(currentPage-1)*recordNum;

set @sql=concat("select ",vclumn_name," from ",vtable_name,
" where ",vtiaojian," order by ",sortcolumn," ",sorttype,
" limit ",startNum,",",recordNum);

#對sql語句進行預編譯
prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;

對於輸出參數的獲取要用一個臨時變量將其值存儲起來,再將該臨時變量的值賦給輸出參數。

set @sql2=concat("select count(*) into @temptotalnum from ",vtable_name," where ",vtiaojian);
prepare stmt2 from @sql2;
execute stmt2;
set countNum = @temptotalnum;#將臨時變量中的數據賦值給輸出參數
deallocate prepare stmt2;
SET countPage=CEILING(countNum/recordNum);
end;


二、在jdbc中執行存儲過程

鑑於要執行的存儲過程中的輸入輸出參數較多,所以,爲數據獲取和存儲的方便起見,新建了一個工具類來存儲各參數中的數據,命名爲PageUtils

public class PageUtils {

	private int currentPage;
	private int pagesize;
	private String tableName;
	private String selections;
	private String condition;
	private String sortColumn;
	private String sortType;
	
	private int totalNum;
	private int totalPage;
	//存儲當前頁的數據
	private List<Object[]> datas;
	
	public int getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}
	public int getPagesize() {
		return pagesize;
	}
	public void setPagesize(int pagesize) {
		this.pagesize = pagesize;
	}
	public String getTableName() {
		return tableName;
	}
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}
	public String getSelections() {
		return selections;
	}
	public void setSelections(String selections) {
		this.selections = selections;
	}
	public String getCondition() {
		return condition;
	}
	public void setCondition(String condition) {
		this.condition = condition;
	}
	public String getSortColumn() {
		return sortColumn;
	}
	public void setSortColumn(String sortColumn) {
		this.sortColumn = sortColumn;
	}
	public String getSortType() {
		return sortType;
	}
	public void setSortType(String sortType) {
		this.sortType = sortType;
	}
	public int getTotalNum() {
		return totalNum;
	}
	public void setTotalNum(int totalNum) {
		this.totalNum = totalNum;
	}
	public int getTotalPage() {
		return totalPage;
	}
	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}
	public List<Object[]> getDatas() {
		return datas;
	}
	public void setDatas(List<Object[]> datas) {
		this.datas = datas;
	}	
}
另建一個執行類來用jdbc連接數據庫執行存儲過程,並將所得的查詢結果和輸出參數全部存儲到PageUtils對象中,然後通過操作對象PageUtils中的list集合即可查看所得數據(這裏主要要注意在執行存儲過程中對輸出參數的處理)。

public class ProcedureDemo{


	public PageUtils procPaging(PageUtils pu) throws SQLException{
		
		//獲取數據庫連接對象
		Class.forName("com.mysql.jdbc.Driver");
 		//獲取預處理命令
		Connection conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306//mydb?username=root&password=123456");

		CallableStatement cs=conn.prepareCall("{call pro_page2 (?,?,?,?,?,?,?,?,?)}");
		cs.setInt(1, pu.getCurrentPage());
		cs.setInt(2, pu.getPagesize());
		cs.setString(3, pu.getTableName());
		cs.setString(4,pu.getSelections());
		cs.setString(5,pu.getCondition());
		cs.setString(6, pu.getSortColumn());
		cs.setString(7,pu.getSortType());
		
		//註冊輸出參數
		cs.registerOutParameter(8, java.sql.Types.INTEGER);
		cs.registerOutParameter(9, java.sql.Types.INTEGER);
		//執行存儲過程
		cs.execute();
		//獲取指定位置的輸出參數集
		int totalNum=cs.getInt(8);
		int totalPage=cs.getInt(9);
		pu.setTotalNum(totalNum);
		pu.setTotalPage(totalPage);
		
		//存儲查詢所得的結果集
		List<Object[]> list=new ArrayList<>();
		//獲取查詢的結果集
		ResultSet rs =cs.getResultSet();
		ResultSetMetaData rsmd = rs.getMetaData();
		// 獲取數據的總列數
		int count = rsmd.getColumnCount();
		while (rs.next()) {
			Object[] objs = new Object[count];
			for (int i = 1; i <= count; i++) {
				String label = rsmd.getColumnLabel(i);
			
				// 獲取一列數據
				Object obj = rs.getObject(label);
				objs[i - 1] = obj;
			}
			list.add(objs);
		}
		pu.setDatas(list);
		return pu;
	}	
	
	public static void main(String[] args) {
		PageUtils pu=new PageUtils();
		pu.setCurrentPage=1;
		pu.setPageSize=10;
		pu.setTableName="employee";		
		procPaging(pu);
	}
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章