SSH整合實現分頁查詢(兩種方式)

JAVA_HORSE發表於2018-11-16

介紹:
使用SSH整合開發,進行分頁查詢,我採用了hibernate的兩種不同物件來操作,第一種:DetachedCriteria離線物件;第一種:是hibernateTemplate模板的HibernateCallback<>()函式回撥,實際上它是一個介面,使用它時,需要實現它裡面的方法。

分頁思路:
剛開始我也覺得分頁查詢很難,但其實理清了思路之後,其實一點都不難。
其實分頁的目的,是為前臺使用者服務的,作用在於讓資料有規則性的顯示給使用者。
重點來了,如何實現呢?
1、使用hibernate框架操作持久層運算元據時,他為我們提供了兩個分頁的函式:setFirstResult() 設定起始查詢索引、setMaxResults()設定每次查詢多少條。還有表的總記錄數,可以使用find(hql).size()來獲取,到此分頁時,持久層所做的工作,就到此結束了。
2、上面說到從資料庫中獲取分頁資料,如果不使用傳參方式進行獲取資料時,那只是一個固定的一頁資料,資料永遠不會變,它不符合我們的前臺需求,前臺客戶所需的功能,是可以靈活的點選上一頁,下一頁或跳頁來顯示資料,因此客戶點選頁數時候,就會向後臺傳遞了引數發出請求,獲取資料。這時候,就需要進行持久層的傳參,來完成靈活的分頁了。該如何傳參,這應該是業務層的事情,service層的任務就是進行傳參,去完成客戶的需求和從資料庫中獲取分好頁的資料,並將分好頁的資料封裝好,並傳給前臺客戶。
3、service層該是如何封裝分頁的資料呢?這時就需要我們自定義一個分頁Bean來獲取分好頁的資料,通過這個Bean來傳給controller層,再傳給客戶。
思路總結:分頁的總思路,只需理解分頁Bean即可,這個bean相當於一艏小船,在來回不停地,將分好頁的資料運輸給前臺,再將前臺給它的資料清單去到service層中取資料,如何取,按照前臺的傳給它的引數來取資料。

第一種分頁方法:DetachedCriteria離線物件
1、實體類:User.java

import java.io.Serializable;
public class User implements Serializable{
	private static final long serialVersionUID = 1L;	
    private int userId;
    private String userName;
    private String userPassword;
    private String userType;
    public User() {		
    }	
   public User(String userName, String userPassword, String userType) {
   	this.userName = userName;
   	this.userPassword = userPassword;
   	this.userType = userType;
   }
   //get與set方法省略......
 }

2、對映檔案:

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.lice.entity">
    <class name="User" table="user">
        <id name="userId" type="int">
            <column name="userId" precision="22" scale="0"/>
            <generator class="identity" />
        </id>
        <property name="userName" type="java.lang.String">
            <column name="userName" not-null="false" length="100" />
        </property>
        <property name="userPassword" type="java.lang.String">
            <column name="userPassword" length="100" not-null="false" />
        </property>
        <property name="userType" type="java.lang.String">
            <column name="userType" length="500" not-null="false"/>
        </property>
    </class>
</hibernate-mapping>

3、自定義PageBean

import java.io.Serializable;
import java.util.List;
/**

- 用於封裝分頁資料物件 
- 伺服器做的事情
- @author 11606
*
 */
public class Page implements Serializable {
  //這三條不是我們能知道的
private int currentPageNum;  //當前頁數 (使用者提供)
private int pageSize=5;        //每頁記錄條數 (設定)
private int totalRecords;      //總記錄數 (從資料庫中查詢)
  //能計算的資料
private int startIndex;      //查詢開始記錄索引
private int totalPageNum;    //總頁數
private List pageData;       //分好頁的結果集 (結果條數為pageSize,設定好的)
  private int  prePageNum;    //上一頁
private int nextPageNum;    //下一頁
  //用於顯示頁碼的屬性,在頁面上最多顯示9頁,當前頁在允許的情況下,永遠居中
private int beginPageNum;
private int endPageNum;

/**
 * 要想使用此類,必須提供兩個引數
 * @param currentPageNum 當前頁
 * @param totalRecords  總記錄條數
 */
public Page(int currentPageNum,int totalRecords) {
	this.currentPageNum = currentPageNum;  //獲取當前頁引數
	this.totalRecords = totalRecords;      //獲取總記錄數
	
	//計算開始索引
	startIndex = (currentPageNum-1)*pageSize;
	
	//計算總頁數
	totalPageNum = totalRecords%pageSize==0? totalRecords/pageSize :totalRecords/pageSize+1;
	
	//計算頁號		
	if(totalPageNum<9) {
		//如果沒有9頁資料庫記錄條數
		beginPageNum=1;
		endPageNum=totalPageNum;			
	}else {
		//前提條件是有9頁資料記錄條數,才執行
		beginPageNum = currentPageNum-4;
		endPageNum = currentPageNum+4;
		if (beginPageNum<1) {
			beginPageNum=1;
			endPageNum=beginPageNum+8;
		}
		if (endPageNum>totalPageNum) {
			endPageNum=totalPageNum;
			beginPageNum=endPageNum-8;
		}		
	}
	
}

public int getPrePageNum() {
	prePageNum = currentPageNum-1;
	if (prePageNum<1) {
		prePageNum=1;
	}
	//計算上一頁
	return prePageNum;
}

public int getNextPageNum() {
	//計算下一頁
	nextPageNum = currentPageNum+1;
	if (nextPageNum>totalPageNum) {
		nextPageNum=totalPageNum;
	}
	return nextPageNum;
}

public int getCurrentPageNum() {
	return currentPageNum;
}

public void setCurrentPageNum(int currentPageNum) {
	this.currentPageNum = currentPageNum;
}

public int getPageSize() {
	return pageSize;
}

public void setPageSize(int pageSize) {
	this.pageSize = pageSize;
}

public int getTotalRecords() {
	return totalRecords;
}

public void setTotalRecords(int totalRecords) {
	this.totalRecords = totalRecords;
}

public int getStartIndex() {
	return startIndex;
}

public void setStartIndex(int startIndex) {
	this.startIndex = startIndex;
}

public int getTotalPageNum() {
	return totalPageNum;
}

public void setTotalPageNum(int totalPageNum) {
	this.totalPageNum = totalPageNum;
}

public List getPageData() {
	return pageData;
}

public void setPageData(List pageData) {
	this.pageData = pageData;
}

public void setPrePageNum(int prePageNum) {
	this.prePageNum = prePageNum;
}

public void setNextPageNum(int nextPageNum) {
	this.nextPageNum = nextPageNum;
}

public int getBeginPageNum() {
	return beginPageNum;
}

public void setBeginPageNum(int beginPageNum) {
	this.beginPageNum = beginPageNum;
}

public int getEndPageNum() {
	return endPageNum;
}

public void setEndPageNum(int endPageNum) {
	this.endPageNum = endPageNum;
}
}

注意:page最重要的有三個引數,是我們不知道,不能少定義,其他的定義可有可無,根據需要
三個引數數:
1、currentPageNum; //當前頁數 (使用者提供)
2、pageSize=5; //每頁記錄條數 (需要設定)
totalRecords; //總記錄數 (從資料庫中查詢)

4、持久層:

4.1UserDao.java

/**
 *分頁查詢
 * @param dCriteria   查詢條
 * @param firstResult  查詢的開始記錄索引
 * @param maxResults   每次查詢的記錄條數
 * @return
 */
List<User> findAllForPage(DetachedCriteria dCriteria,int firstResult,int maxResults);     

/**
 *  查詢總記錄條數
 * @param dCriteria 查詢條件
 * @return
 */
int findTotalRecords(DetachedCriteria dCriteria);

4.2UserDaoImpl.java

/**
 *  查詢總記錄條數
 * @param dCriteria 查詢條件
 * @return
 */
@Override
public int findTotalRecords(DetachedCriteria dCriteria) {
	//hibernateTemplate.findByCriteria(dCriteria) 返回的的是集合物件,不是int
	dCriteria.setProjection(Projections.count("userId")); //等同於 select count(*);獲取表總記錄數
	List<Long> list = (List<Long>) hibernateTemplate.findByCriteria(dCriteria);
	return list.isEmpty()? 0:list.get(0).intValue();//獲取這個集合的數量,即獲取表中總記錄數
}

/**
 *分頁查詢
 * @param dCriteria   查詢條
 * @param firstResult  查詢的開始記錄索引
 * @param maxResults   每次查詢的記錄條數
 * @return
 */
@Override
public List<User> findAllForPage(DetachedCriteria dCriteria, int firstResult, int maxResults) {
	//將之前的設定清空
	dCriteria.setProjection(null);
	return (List<User>) hibernateTemplate.findByCriteria(dCriteria, firstResult, maxResults);
}

值得注意的是:dCriteria.setProjection(null);是因為,一個物件被呼叫了兩次,需要將dCriteria物件的值清空,不然查詢不出來。

5、業務層:
5.1UserService.java

/**
 * 分頁查詢業務
 * @param dCriteria  查詢條件
 * @param num        當前頁   (業務方法中無法獲取,使用者點選,傳引數進來)
 * @return  page     封裝好的分頁資訊
 */
Page findAllForPage(DetachedCriteria dCriteria,Integer num);          

5.2UserServiceImpl.java

/**
 * 分頁查詢業務
 * @param dCriteria  查詢條件
 * @param num        當前頁   (業務方法中無法獲取,使用者點選,傳引數進來)
 * @return  page     封裝好的分頁資訊
 */
@Override
public Page findAllForPage(DetachedCriteria dCriteria, Integer num) {
	//1.準備當前頁的資訊
	int currentPageNum = 1;
	if (num!=null) {
		currentPageNum = num;
	}
	//2.獲取總記錄條數
	int  totalRecords = userDao.findTotalRecords(dCriteria);
	//3.建立page物件
	Page page = new Page(currentPageNum, totalRecords);
	//4.使用page物件中的資料,查詢帶有分頁的結果集
	List<User> pageData = userDao.findAllForPage(dCriteria, page.getStartIndex(), page.getPageSize());
	//5.將查詢出來的資料封裝到page物件
	page.setPageData(pageData);
	//返回page物件
	return page;
}

6、控制層

import javax.annotation.Resource;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

import cn.lice.entity.User;
import cn.lice.service.UserService;
import cn.lice.utils.Page;
@Controller("userQueryAction")
@Scope("prototype")
@ParentPackage("struts-default")
@Namespace("/user")
@Results({
	@Result(name="success", type="dispatcher",location="/jsp/user/showuser.jsp"),
	@Result(name="error", type="dispatcher",location="/jsp/error/error.jsp")
})
public class UserQueryAction extends ActionSupport implements ModelDriven<User>{

private static final long serialVersionUID = 213518999309249850L;
private User  user = new User();
@Override
public User getModel() {
	return user;
}

private Page page;	//聲名page物件值棧
private Integer num;  //當前頁
//注入業務層屬性
@Resource(name="userService")
private UserService userService;

@Action("userQuery")
public String userQuery() throws Exception {
	DetachedCriteria dCriteria = DetachedCriteria.forClass(User.class);//等同from User;
	//獲取所有使用者
	 page=userService.findAllForPage(dCriteria, num);
	 ServletActionContext.getRequest().setAttribute("page", page);
	return SUCCESS;	
}

//page
public Page getPage() {
	return page;
}
public void setPage(Page page) {
	this.page = page;
}
public Integer getNum() {
	return num;
}

public void setNum(Integer num) {
	this.num = num;
}

}

7、jsp檔案

<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
    <%@ taglib prefix="s" uri="/struts-tags" %>
}
<meta charset="utf-8">
<title>使用者資訊</title>
<script type="text/javascript">
 	function deleteUser(userId) {
		var sure = window.confirm("確定刪除嗎?");
		if (sure) {
			window.location.href="${pageContext.request.contextPath}/user/delete.action?userId="+userId;
		}
	}
 	function updateUser(userId) {
		window.location.href="${pageContext.request.contextPath}/user/editUIUser.action?userId="+userId;

</script>
</head>
<body>
	<h3>使用者資訊</h3>
	<s:form action="/user/userQuery.action">
	<s:hidden name="num" value="" id="pagenum">/s:hidden
	<table border="1" width="400" cellpadding="0" cellspacing="0" >
		<tr>
			<td>使用者ID</td>
			<td>使用者名稱</td>
			<td>使用者密碼</td>
			<td>使用者型別</td>
			<td>是否刪除</td>
			<td>是否更新</td>
		</tr>
		<s:iterator value="#request.page.pageData" var="page">
			<tr>
				<td align="center"><s:property value="#page.userId"/></td>
				<td align="center"><s:property value="#page.userName"/></td>
				<td align="center"><s:property value="#page.userPassword"/></td>
				<td align="center"><s:property value="#page.userType"/></td>
				<td><s:a href="javascript:updateUser('%{userId}')">更新/s:a</td>
				<td><s:a href="javascript:deleteUser('%{userId}')">刪除/s:a</td>
			</tr>
		/s:iterator
	</table>
	<table>
		<tr>
			<td align="center">
				<!-- 分頁開始  -->
				<%@ include file="/jsp/commons/page.jsp" %>
				<!-- 分頁結束 -->
			</td>
		</tr>
	</table>
	/s:form
	<br>
	新增使用者
</body>
</html>

8、公共引用的分頁jsp檔案

<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<script type="text/javascript">
	function topage(num) {
		//1.給表單提供一個隱藏域,用於提供當前頁
		document.getElementById("pagenum").value = num;
		//提交表單
		document.forms[0].submit();
	}
</script>
首頁 上一頁 ${snum} 下一頁 末頁       第${page.currentPageNum }頁 /共${page.totalPageNum }頁
9、效果顯示

在這裡插入圖片描述

第二種方法:hibernateTemplate模板的HibernateCallback<>()函式回撥
1、Dao層

import java.util.List;
import cn.itcast.pojo.OrderItem;

/**

- 訂單分頁持久化介面
- @author 11606
*
 */
public interface OrderDao {
  /**
  - 分頁查詢
  - @param hql   查詢條件
  - @param firstResult    查詢開始記錄索引
  - @param maxResults     查詢最大記錄數
  - @return  返回一頁資料
*/
public List<OrderItem> findForPage(final String hql,final int firstResult,final int maxResults);
  /**
  - 查詢總記錄數
  - @param hql  查詢條件
  - @return 總記錄數
*/
public int findTotalRow(final String hql);
}

實現類:

import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.orm.hibernate5.HibernateCallback;
import org.springframework.orm.hibernate5.HibernateTemplate;

import cn.itcast.dao.OrderDao;
import cn.itcast.pojo.OrderItem;
/**

- 分頁dao層實現類
- @author 11606
*
 */
public class OrderDaoImpl implements OrderDao {
  private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
	this.hibernateTemplate = hibernateTemplate;
}
  /**
  - 分頁查詢
  - @param hql   查詢條件
  - @param firstResult    查詢開始記錄索引
  - @param maxResults     查詢最大記錄數
  - @return 返回一頁的資料
*/
@Override
public List<OrderItem> findForPage(String hql, int firstResult, int maxResults) {
List<OrderItem> list = (List<OrderItem>) hibernateTemplate.execute(new HibernateCallback<List<OrderItem>>() {

@Override
public List<OrderItem> doInHibernate(Session session) throws HibernateException {
	Query query = session.createQuery(hql);  //查詢條件
	query.setFirstResult(firstResult);      //起始查詢索引
	query.setMaxResults(maxResults);        //查詢最大記錄數
	List<OrderItem> list = query.list();
	//session.close();
    return list;
}
  /**
  - 查詢總記錄數
  - @param hql  查詢條件
  - @return  返回總記錄數
*/
@Override
public int findTotalRow(String hql) {
return hibernateTemplate.find(hql).size(); //總記錄數
}

}

2、Service層

public interface OrderService {
/**
 * 訂單業務分頁查詢
 * @param hql  查詢條件
 * @param num  當前頁數
 * @return 返回一頁資料結果集
 */
public PageBean<OrderItem> findForPage(String hql,Integer num);
}

實現類:

import java.util.List;
import cn.itcast.bean.PageBean;
import cn.itcast.dao.OrderDao;
import cn.itcast.pojo.OrderItem;
import cn.itcast.service.OrderService;

public class OrderServiceImpl implements OrderService {

private OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
	this.orderDao = orderDao;
}
/**
 * 訂單業務分頁查詢
 * @param hql  查詢條件
 * @param num  當前頁數
 * @return 返回一頁資料結果集
 */
@Override
public PageBean<OrderItem> findForPage(String hql, Integer num) {
	//2.設定當前頁資訊
	int currentPageNum =1 ;
	if (num!=0) {
		currentPageNum = num;
	}
	//3.總記錄數
	int  totalRecords = orderDao.findTotalRow(hql);
	
	//1.建立分頁物件
	PageBean<OrderItem> pageBean = new PageBean<>(currentPageNum, totalRecords);
	//4.使用page物件中的資料,查詢帶有分頁的結果集
	List<OrderItem> list = orderDao.findForPage(hql, pageBean.getStartIndex(), pageBean.getPageSize());
	//2.給分頁物件傳入結果集
	pageBean.setPageData(list);		
	return pageBean;
}
}

3、controller層

import com.opensymphony.xwork2.ActionSupport;
/**

- 分頁action
- @author 11606
*
 */

import cn.itcast.bean.PageBean;
import cn.itcast.pojo.OrderItem;
import cn.itcast.service.OrderService;
public class PageAction extends ActionSupport {

private OrderService orderService;
public void setOrderService(OrderService orderService) {
	this.orderService = orderService;
}

private int num; //當前頁數
private PageBean<OrderItem> pageBean; //分頁值棧
public String pageForOrder() {
	String hql = "from OrderItem";
	pageBean = orderService.findForPage(hql, num);
	return SUCCESS;
}
public int getNum() {
	return num;
}
public void setNum(int num) {
	this.num = num;
}
public PageBean<OrderItem> getPageBean() {
	return pageBean;
}
public void setPageBean(PageBean<OrderItem> pageBean) {
	this.pageBean = pageBean;
}
}

兩種方法:所用的分頁Bean是一樣的,頁面jsp檔案也是一樣。
值得一提的是第二種方法使用HibernateCallback<List>()函式回撥,此種方法可以取得session物件,可以很靈活的運算元據庫,但總是要實現介面方法,也有不便之處。兩種方法各有不同,僅供參考!
分頁查詢到此結束了,如果有錯誤請指出,共同學習,一起進步!當然分頁查詢可以有很多種方法,也可以藉助一些很方便的外掛來完成了,大家可以分享一下,

相關文章