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>
至此分页功能就大功告成了,我所使用的这种运用接口来进行分页的方法,优点就是独立性高,可以很轻松的往你的项目里面添加。