struts2+ibatis分页
沙逛鱼mailluzhou@163.com
刚开始学这几个框架没多久,遇到很多问题是在所难免的,这两天写用户信息管理模块,要用到分页,在网上也看了不少,很多都是用ibatis里自带的方法写,不过实现方式好像是先从数据库中读取全部数据,然后再分,感觉数据量大的时候,效率肯定会很慢,在hibernate里有专门分页的方法(函数),ibatis也有,但是针对少量数据的时候能用。
原先用jdbc写的时候,分页很简单,用哪部分,就读取那部分并显示出来,感觉这个方法挺简单,于是我就用了这个思想,每个主流数据库基本上都有自己的查询特定数据的sql语句,我的数据库用的是mssql2000的,它的分页查询sql语句是:pagesize:每页显示记录数currentpage:当前页数1
select*from(selectTOPpagesize*FROM(SELECTTOPpagesize*cureentpage*fromuser_tableORDERBYidASC)asaSysTableORDERBYidDESC)asbSysTableORDERBYidASC
在网上看到一个用基于struts2+spring+hibernate写的管理系统,我用了他的分页思想,和部分代码,在获取数据的时候,他用的是hibernate,而我给转化成是ibatis。就从表现层一步一步开始吧!
(一)表现层
memberlist.jsp的主要代码
1 1 沙逛mailluzhou@163.com 共 第 共 (二)控制层 MemberListAction 上面文件里用到memberlist这个action的getuserslist方法,下面是memberlist这个action: 这个action通过spring注入了usersservice业务组件,另外还有Pager,pager类里包括查询分页返回的用户信息列表,currentPage和pagerMethod是接收前台页面传来的参数。packagecom.netshop.action.admin; importcom.opensymphony.xwork2.ActionSupport;importcom.opensymphony.xwork2.ActionContext;importcom.netshop.service.UsersService;importjava.util.Map; 2 沙逛mailluzhou@163.com importjava.util.List; importjava.util.ArrayList;importcom.netshop.util.Pager;importcom.netshop.domain.Users;/*** *@authorLuZhou*/ publicclassMemberListActionextendsActionSupport{publicMemberListAction(){} protectedPagerpager;//查看(五) protectedStringcurrentPage;protectedStringpagerMethod; privateUsersServiceusersservice;privateListusers;publicPagergetPager(){returnpager;} publicvoidsetPager(Pagerpager){this.pager=pager;} publicStringgetPagerMethod(){returnpagerMethod;} publicvoidsetPagerMethod(StringpagerMethod){this.pagerMethod=pagerMethod;} publicStringgetCurrentPage(){returncurrentPage;} publicvoidsetCurrentPage(StringcurrentPage){this.currentPage=currentPage;} publicListgetUsers(){ returnusers;} 3 沙逛mailluzhou@163.com publicvoidsetUsers(Listusers){ this.users=users;} publicvoidsetUsersservice(UsersServiceusersservice){ this.usersservice=usersservice;} publicStringgetuserslist()throwsException{ Mapsession=ActionContext.getContext().getSession();if(null!=session.get(\"user\")){ pager=usersservice.getPager(getCurrentPage(),getPagerMethod()); users=(ArrayList)pager.getElements(); this.setCurrentPage(String.valueOf(pager.getCurrentPage()));returnSUCCESS;}else returnERROR; }} 上面的memberlist这个acion配置,如下:struts.xml里的action 我使用spring来管理所有组件的包括action,spring配置文件里的部分代码: 4 沙逛mailluzhou@163.com (三)业务逻辑层 上面usersservice的getPager()方法,其实是调用了我写的dao层basedao的方法getPager(),basedao是个基类,以后其他继承自该类的,都可以实现分页。basedao的代码 packagecom.netshop.dao; importorg.springframework.orm.ibatis.support.SqlMapClientDaoSupport;importorg.springframework.orm.ibatis.SqlMapClientTemplate;importcom.netshop.util.Pager;importjava.util.List; importjava.util.ArrayList; importcom.netshop.domain.Users;/** *@author:LuZhou *@E-mail:mailluzhou@163.com*@version:1.0*@Date:2009-5-10**/ publicclassBaseDao extendsSqlMapClientDaoSupport{ protectedSqlMapClientTemplatesmcTemplate=this.getSqlMapClientTemplate(); //获取查询数据的总记录,用于计算页数时用到publicintgetCounts(){ return((Integer)smcTemplate.queryForObject(\"getCounts\")).intValue();//查看(四)} //根据表现层传过来的页面和表现层传过来的方法获取特定页面的数据,在控制层action会调用这个方法, publicPagergetPager(StringcurrentPage,StringpagerMethod)。{ inttotalRows=this.getCounts();//先获取总记录数,也是用sql语句获取。Listitems=newArrayList();Pagerpager; pager=newPager(totalRows); 5 沙逛mailluzhou@163.com if(currentPage!=null){ pager.refresh(Integer.parseInt(currentPage));} if(pagerMethod!=null){ if(pagerMethod.equals(\"first\")){ pager.first();} elseif(pagerMethod.equals(\"previous\")){ pager.previous();} elseif(pagerMethod.equals(\"next\")){ pager.next();} elseif(pagerMethod.equals(\"last\")){ pager.last();}} /* 通过sqlmap查询特定数据,“getListByPager”需要传给他两个参数,就是最开始讲的mssql2000分页sql语句用到得两个参数pagesize和cureentpage,这两个参数都封装在pager类里,因为sql语句中要得到pagesize和cureentpage的乘积,在配置文件中直接获取不到,所以我将pagesize和cureentpage的乘积存放到另一个参数里,在pager类里能看到,就是pageSizeCurrentPage。*/ items=(ArrayList)smcTemplate.queryForList(\"getListByPager\查看(四) pager.setElements(items);//将获取的列表赋给pager的elements,然后返回给前台。returnpager; }} 6 沙逛mailluzhou@163.com (四) 看看sqlmap的配置文件 SELECTcount(id)FROMusers]]> 用下面的语句无错误,不过此时的$pageSizeCurrentPage$,跟上面的不一样, $pageSizeCurrentPage$=pagesize*(当前页数-1),在Pager.java里已经改过了。 SELECTTOP$pageSize$*FROMproductsWHEREIDNOTIN(SELECTTOP$pageSizeCurrentPage$IDFROMproductsORDERBYIDDESC)ORDERBYIDDESC 上面需要说明的是,给id=\"getListByPager\"传递参数的时候,必须用$pageSize$这种方式,而非#pageSize#,用它在编译的时候会出错,获取不到pageSize这个值 就像我们用jdbc时的Statement和PreparedStatement一样,用#pageSize#和PreparedStatement一样的性质,先预处理,而用Statement是直接在sql语句参数化之前,将数值注入到sql语句中,$pageSize$就是这个目的,当然也会面临sql注入的问题,不过这里还好。这也是能分页的关键所在。 (五)辅助类 packagecom.netshop.util; importjava.util.List;/*** *@author:LuZhou*@Email:mailluzhou@163.com*@version:1.0*@Date:2009-5-10 7 沙逛mailluzhou@163.com * *@desciprion:*/ publicclassPager{ privateinttotalRows;//记录总数 privateintpageSize=4;//没页显示记录数privateintcurrentPage=1;//当前页码privateinttotalPages;//总页数 privateintstartRow;//当前页码开始记录数privateListelements;//获取的记录列表 privateintpageSizeCurrentPage;//记录currentPage与pageSize的乘积,在ibatis的sqlmap配置文件里要用到 publicPager(){} publicPager(inttotalRows){ this.totalRows=totalRows; //更新于2009-6-11原先为totalPages=totalRows/pageSize;//解决totalRows为0时,页面出错!如下://-----------------------------------------------totalPages=totalRows==0?1:totalRows/pageSize;//-------------------------------------------intmod=totalRows%pageSize;if(mod>0){ totalPages++;} currentPage=1;startRow=0;} publicvoidfirst(){ currentPage=1;startRow=0;} publicvoidprevious(){ 8 沙逛mailluzhou@163.com if(currentPage==1){ return;} currentPage--; startRow=(currentPage-1)*pageSize;} publicvoidnext(){ if(currentPage startRow=(currentPage-1)*pageSize;} publicvoidlast(){ currentPage=totalPages; startRow=(currentPage-1)*pageSize;} publicvoidrefresh(intcurrentPage){ this.currentPage=currentPage;if(currentPage>totalPages) last(); } publicintgetTotalRows(){ returntotalRows;} publicvoidsetTotalRows(inttotalRows){ this.totalRows=totalRows;} publicintgetPageSize(){ returnpageSize;} 9 沙逛mailluzhou@163.com publicvoidsetPageSize(intpageSize){ this.pageSize=pageSize;} publicintgetCurrentPage(){ returncurrentPage;} publicvoidsetCurrentPage(intcurrentPage){ this.currentPage=currentPage;} publicintgetTotalPages(){ returntotalPages;} publicvoidsetTotalPages(inttotalPages){ this.totalPages=totalPages;} publicintgetStartRow(){ returnstartRow;} publicvoidsetStartRow(intstartRow){ this.startRow=startRow;} publicListgetElements(){ returnelements;} publicvoidsetElements(Listelements){ this.elements=elements; 10 沙逛mailluzhou@163.com }/* *一个错误,浪费了我大半天的时间,整个分页代码走查了好几遍,挨个又测试了一遍,原来在这出错。 *getPageSizeCurrentPage()方法原先写的时候写顺手了,直接返回pageSizeCurrentPage, *其实应该返回pageSize*currentPage,难怪sqlMap里老是得不到数据,郁闷了半天,终于搞定。**/ publicintgetPageSizeCurrentPage(){ //returnpageSize*currentPage;原先分页语句中的参数,不过会出错。returnpageSize*(currentPage-1)} publicvoidsetPageSizeCurrentPage(){ //this.pageSizeCurrentPage=pageSize*currentPage;this.pageSizeCurrentPage=pageSize*(currentPage-1)}} 上面就是具体的实现过程。 11 因篇幅问题不能全部显示,请点此查看更多更全内容