ssh整合开发一直存在很多让人头痛的问题,而分页功能我事先也找了很多网上其他的帖子,但是里面或多或少都存在一些问题。贴别是网上讲的分页大都是hibernate3.0的,可能跟我们目前实际开发中所使用的hibernate版本不同,所以笔者在这里编写了对应hibernate4.0的分页接口方法。在这里我就来跟大家一起分享一下自己开发时遇到的一些问题,以及解决和优化的一些方案。
首先直接上干货,分页的ssh具体实现。
1、DAO层接口的设计,在MemberDao接口中定义了如下两个方法:
import java.util.List;
import entity.Food;
public interface MemberDao {
//省略了其他的代码
/**
* 分页查询
* @param hql 查询的条件
* @param offset 开始记录
* @param length 一次查询几条记录
* @return
*/
public List<Food> queryForPage(final String hql,final int offset,final int length);
/**
* 查询所有记录数
* @param hql 查询的条件
* @return 总记录数
*/
public int getAllRowCount(String hql);
}
2、DAO层实现类MemberDaoImpl对上面两个方法的实现如下:
(做这一步是我要特别提醒大家一下,笔者就曾在这里犯过错误,hibernate 3.0里面查询数据的一些方式跟hibernate 4.0里面是不一样的。所以开发的时候一定要看你项目里面的包到底是那个版本的,这里我就以现在流行的hibernate 4.0的方法来讲好了。)
import java.sql.SQLException;
import java.util.*;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.huizhi.common.HibernateSessionFactory;
import entity.Food;
public class MemberDaoImpl implements MemberDao {
//省略了其他的代码
private SessionFactory sessionFactory;
private MemberDao memberDao;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public MemberDao getMemberDao() {
return memberDao;
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
/**
* 分页查询
* @param hql 查询的条件
* @param offset 开始记录
* @param length 一次查询几条记录
* @return
*/
public List<Food> queryForPage(final String hql,final int offset,final int length){
Session session = sessionFactory.openSession();
List<Food> foodlist=null;
try{
Query query=session.createQuery(hql);
query.setFirstResult(offset);
query.setMaxResults(length);
foodlist = query.list();
}catch(RuntimeException re){
throw re;
}
session.close();
return foodlist;
}
/*
public List queryForPage(final String hql,final int offset,final int length){
List list = getHibernateTemplate().executeFind(new HibernateCallback(){
public Object doInHibernate(Session session) throws HibernateException,SQLException{
Query query = session.createQuery(hql);
query.setFirstResult(offset);
query.setMaxResults(length);
List list = query.list();
return list;
}
});
return list;
}
*/
/**
* 查询所有记录数
* @return 总记录数
*/
public int getAllRowCount(String hql){
Session session = sessionFactory.openSession();
List<Food> foodlist1=null;
try{
Query query=session.createQuery(hql);
foodlist1 = query.list();
}catch(RuntimeException re){
throw re;
}
session.close();
return foodlist1.size();
}
}
3、下面我们来新建一个保存分页信息的类PageBean,具体代码如下:
package entity;
import java.util.List;
public class PageBean {
private List list; //要返回的某一页的记录列表
private int allRow; //总记录数
private int totalPage; //总页数
private int currentPage; //当前页
private int pageSize; //每页记录数
private boolean isFirstPage; //是否为第一页
private boolean isLastPage; //是否为最后一页
private boolean hasPreviousPage; //是否有前一页
private boolean hasNextPage; //是否有下一页
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public int getAllRow() {
return allRow;
}
public void setAllRow(int allRow) {
this.allRow = allRow;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
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 void init(){
this.isFirstPage = isFirstPage();
this.isLastPage = isLastPage();
this.hasPreviousPage = isHasPreviousPage();
this.hasNextPage = isHasNextPage();
}
/**
* 以下判断页的信息,只需getter方法(is方法)即可
* @return
*/
public boolean isFirstPage() {
return currentPage == 1; // 如是当前页是第1页
}
public boolean isLastPage() {
return currentPage == totalPage; //如果当前页是最后一页
}
public boolean isHasPreviousPage() {
return currentPage != 1; //只要当前页不是第1页
}
public boolean isHasNextPage() {
return currentPage != totalPage; //只要当前页不是最后1页
}
/**
* 计算总页数,静态方法,供外部直接通过类名调用
* @param pageSize 每页记录数
* @param allRow 总记录数
* @return 总页数
*/
public static int countTotalPage(final int pageSize,final int allRow){
int totalPage = allRow % pageSize == 0 ? allRow/pageSize : allRow/pageSize+1;
return totalPage;
}
/**
* 计算当前页开始记录
* @param pageSize 每页记录数
* @param currentPage 当前第几页
* @return 当前页开始记录号
*/
public static int countOffset(final int pageSize,final int currentPage){
final int offset = pageSize*(currentPage-1);
return offset;
}
/**
* 计算当前页,若为0或者请求的URL中没有"?page=",则用1代替
* @param page 传入的参数(可能为空,即0,则返回1)
* @return 当前页
*/
public static int countCurrentPage(int page){
final int curPage = (page==0?1:page);
return curPage;
}
}
4、Service层接口的设计:
package dao;
import entity.PageBean;
public interface MemberService {
//省略其他的代码
/**
* 分页查询
* @param currentPage 当前第几页
* @param pageSize 每页大小
* @return 封闭了分页信息(包括记录集list)的Bean
*/
public PageBean queryForPage(int pageSize,int currentPage);
}
5、Service层实现类的部分内码如下:
package dao;
import java.util.List;
import entity.Food;
import entity.PageBean;
public class MemberServiceImpl implements MemberService {
//通过applicationContext.xml配置文件注入MemberDao的值
private MemberDao memberDao;
public MemberDao getMemberDao() {
return memberDao;
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
/**
* 分页查询
* @param currentPage 当前第几页
* @param pageSize 每页大小
* @return 封闭了分页信息(包括记录集list)的Bean
*/
public PageBean queryForPage(int pageSize,int page){
final String hql = "from Food"; //查询语句
int allRow = memberDao.getAllRowCount(hql); //总记录数
int totalPage = PageBean.countTotalPage(pageSize, allRow); //总页数
final int offset = PageBean.countOffset(pageSize, page); //当前页开始记录
final int length = pageSize; //每页记录数
final int currentPage = PageBean.countCurrentPage(page);
List<Food> list = memberDao.queryForPage(hql,offset, length); //"一页"的记录
//把分页信息保存到Bean中
PageBean pageBean = new PageBean();
pageBean.setPageSize(pageSize);
pageBean.setCurrentPage(currentPage);
pageBean.setAllRow(allRow);
pageBean.setTotalPage(totalPage);
pageBean.setList(list);
pageBean.init();
return pageBean;
}
}
6.这是我的action里面的方法
import com.opensymphony.xwork2.ActionSupport;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import dao.MemberService;
import dao.SceneManage;
import entity.*;
import dao.Pagination;
@SuppressWarnings("serial")
public class FoodShowAction extends ActionSupport{
//通过applicationContext.xml配置文件注入memberService的值
private MemberService memberService;
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
private int page; //第几页
private PageBean pageBean; //包含分布信息的bean
public int getPage() {
return page;
}
public void setPage(int page) { //若URL中无此参数,会默认为第1页
this.page = page;
}
public PageBean getPageBean() {
return pageBean;
}
public void setPageBean(PageBean pageBean) {
this.pageBean = pageBean;
}
@Override
public String execute() throws Exception {
//分页的pageBean,参数pageSize表示每页显示记录数,page为当前页
this.pageBean = memberService.queryForPage(6, page);
return "success";
}
}
一般的帖子到这里就结束了,但是我这个是超级详细的,接下来的是struts.xml和 applicationContext.xml里面的配置内容,新手们接好干货吧
7.struts.xml
<action name="foodShowAction" class="FoodShowAction">
<result name="fail">/error.jsp </result>
<result name="success">/food1.jsp</result>
</action>
记住,这里的FoodShowAction里面的"sucess"所对应的是
<result name="success">/food1.jsp</result>
这里面的food1.jsp页面
8.applicationContext.xml
<bean id="memberService" class="dao.MemberServiceImpl" abstract="false"
lazy-init="default" autowire="default" dependency-check="default">
<property name="memberDao">
<ref bean="memberDao" />
</property>
</bean>
<bean id="memberDao" class="dao.MemberDaoImpl" >
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="FoodShowAction" class="com.huizhi.action.FoodShowAction" scope="prototype">
<property name="memberService">
<ref bean="memberService" />
</property>
</bean>
9.jsp页面的显示(笔者在这里是直接把分页做成了一个单独的page.jsp,你在需要分页的页面只需要includ这个page.jsp就可以了)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'page.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
共<s:property value="pageBean.allRow"/> 条记录
共<s:property value="pageBean.totalPage"/> 页
当前第<s:property value="pageBean.currentPage"/>页<br/>
<s:if test="%{pageBean.currentPage == 1}">
第一页 上一页
</s:if>
<s:else>
<a href="foodShowAction?page=1">第一页</a>
<a href="foodShowAction?page=<s:property value="%{pageBean.currentPage-1}"/>">上一页</a>
</s:else>
<s:if test="%{pageBean.currentPage != pageBean.totalPage}">
<a href="foodShowAction?page=<s:property value="%{pageBean.currentPage+1}"/>">下一页</a>
<a href="foodShowAction?page=<s:property value="pageBean.totalPage"/>">最后一页</a>
</s:if>
<s:else>
下一页 最后一页
</s:else>
</body>
</html>
至此分页功能就大功告成了,我所使用的这种运用接口来进行分页的方法,优点就是独立性高,可以很轻松的往你的项目里面添加。