之前项目中使用的是 richfaces自带的分页组件开发,但是性能上存在很大问题,所以需要使用数据库分页,这篇文章的主要内容是从网上借鉴过来的,但是网上大多是基于JSF1.2+Rf3.2的基础上进行分页的,我把代码稍微改了下,发现可以在JSF2.0+RF4.0的基础上使用!
?
dao层
?
//自定义分页 public int datasetSize(){ try { String queryString = "select count(*) from Book"; Query query = em.createQuery(queryString); return Integer.parseInt(query.getSingleResult() .toString()); } catch (RuntimeException re) { throw re; } } @SuppressWarnings("unchecked") public List<GoodsType> findAll(int startRow,int pageSize) { try { final String queryString = "select model from Book model"; Query query = em.createQuery(queryString); query.setFirstResult(startRow); query.setMaxResults(pageSize); return query.getResultList(); } catch (RuntimeException re) { throw re; } }
?
DataPage.java?
?
package com.page; import java.util.List; public class DataPage { /** * 将需要的页的数据封装到一个DataPage中去, 这个类表示了我们需要的一页的数据,<br> * 里面包含有三个元素:datasetSize,startRow,和一个用于表示具体数据的List。<br> * datasetSize表示了这个记录集的总条数,查询数据的时候,使用同样的条件取count即可,<br> * startRow表示该页的起始行在数据库中所有记录集中的位置 */ private int datasetSize; private int startRow; private List data; /** * * @param datasetSize * 数据集大小 * @param startRow * 起始行 * @param data * 数据list */ public DataPage(int datasetSize, int startRow, List data) { this.datasetSize = datasetSize; this.startRow = startRow; this.data = data; } /** * * @return */ public int getDatasetSize() { return datasetSize; } public int getStartRow() { return startRow; } /** * * @return 已填充好的数据集 */ public List getData() { return data; } }
?
PageListBaseBean.java
?
package com.page; /** * TODO 带分页功能的基类 * * @author <a href="mailto:tianlu@jsecode.com">TianLu</a> * @version $Rev$ <br> * $Id$ */ public abstract class PageListBaseBean { /** * 当前页码,跟dataSroller的page属性绑定 */ protected int scrollerPage = 1; /** * 当前页面大小 */ protected int pageSize = 10; /** * 默认数据模型,如果你有多个数据集需要分页,请自定义PagedListDataModel和相应的getDataModel方法 */ protected PageListDataModel defaultDataModel; public int getScrollerPage() { return scrollerPage; } public void setScrollerPage(int scrollerPage) { this.scrollerPage = scrollerPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public abstract PageListDataModel getDefaultDataModel(); }
?
PageListDataModel.java?
?
package com.page; import java.io.Serializable; import javax.faces.model.DataModel; public abstract class PageListDataModel extends DataModel implements Serializable { int pageSize; int rowIndex; DataPage page; /** * 创建一个datamodel显示数据,每一页指定的行数。 */ public PageListDataModel(int pageSize) { super(); this.pageSize = pageSize; this.rowIndex = -1; this.page = null; } /** * 数据是通过一个回调fetchData方法获取,而不是明确指定一个列表 */ public void setWrappedData(Object o) { if (o instanceof DataPage) { this.page = (DataPage) o; } else { throw new UnsupportedOperationException(" setWrappedData "); } } public int getRowIndex() { return rowIndex; } /** * 指定的“当前行“在DataSet中.请注意,UIData组件会重复调用这个方法通过getRowData获取使用表中的对象! * */ public void setRowIndex(int index) { rowIndex = index; } /** * 返回的总数据集大小(不只是的行数在当前页面! ) 。 */ public int getRowCount() { return getPage().getDatasetSize(); } /** * 返回DataPage对象;如果目前还没有fetchPage一个。请注意,这并不保证datapage返回包含当前rowIndex行;见getRowData 。 */ private DataPage getPage() { if (page != null) { return page; } int rowIndex = getRowIndex(); int startRow = rowIndex; if (rowIndex == -1) { // even when no row is selected, we still need a page // object so that we know the amount of data available. startRow = 0; } // invoke method on enclosing class page = fetchPage(startRow, pageSize); return page; } /** * 返回相应的对象到当前rowIndex 。如果目前DataPage对象缓存不包括该指数则通过fetchPage找到适当的页面。 */ public Object getRowData() { if (rowIndex < 0) { throw new IllegalArgumentException( " Invalid rowIndex for PagedListDataModel; not within page "); } // ensure page exists; if rowIndex is beyond dataset size, then // we should still get back a DataPage object with the dataset size // in it if (page == null) { page = fetchPage(rowIndex, pageSize); } int datasetSize = page.getDatasetSize(); int startRow = page.getStartRow(); int nRows = page.getData().size(); int endRow = startRow + nRows; if (rowIndex >= datasetSize) { throw new IllegalArgumentException(" Invalid rowIndex "); } if (rowIndex < startRow) { page = fetchPage(rowIndex, pageSize); startRow = page.getStartRow(); } else if (rowIndex >= endRow) { page = fetchPage(rowIndex, pageSize); startRow = page.getStartRow(); } return page.getData().get(rowIndex - startRow); } public Object getWrappedData() { return page.getData(); } /** * 如果rowIndex的值在DataSet中,返回真;请注意,它可能是匹配一行而不是当前DataPage缓存; * 如果是的话当getRowData调用请求页面也会调用fetchData方法。 */ public boolean isRowAvailable() { DataPage page = getPage(); if (page == null) { return false; } int rowIndex = getRowIndex(); if (rowIndex < 0) { return false; } else if (rowIndex >= page.getDatasetSize()) { return false; } else { return true; } } /** * 受管bean必须实现此方法 */ public abstract DataPage fetchPage(int startRow, int pageSize); /** * 进行删除等操作后会立即改变列表项并且返回列表页的,请调用此方法,用于刷新列表。 */ public void refresh() { if (this.page != null) { this.page = null; getPage(); } } }
?
后台bean
?
package com.bean; import java.util.List; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import com.ejb.BookDao; import com.entity.Book; import com.page.DataPage; import com.page.PageListBaseBean; import com.page.PageListDataModel; @ManagedBean @SessionScoped // 或换成ViewScoped public class BookBean extends PageListBaseBean implements Serializable{ private BookDao dao; public GoodsTypeBean() { try { Context ctx = new InitialContext(); java.util.Properties props = new java.util.Properties(); props.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory"); props.setProperty("java.naming.provider.url", "localhost:1099"); props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming"); ctx = new javax.naming.InitialContext(props); dao = (BookDao) ctx.lookup("BookDaoImpl/remote"); } catch (NamingException e) { e.printStackTrace(); } } @Override public PageListDataModel getDefaultDataModel() { if (defaultDataModel == null) { defaultDataModel = new PageListDataModel(pageSize) { public DataPage fetchPage(int startRow, int pageSize) { // call enclosing managed bean method to fetch the data List<Book> list=dao.findAll(startRow, pageSize); return new DataPage(dao.datasetSize(), startRow, list); } }; } return defaultDataModel; } }?
?
?
前台:xhtml
?
<f:view> <h:form id="showBookForm"> <div id="goodsInfoDiv" style="margin-top: 5px;"> <rich:dataTable id="bookList" styleClass="richDataTableStyle" rows="10" align="center" value="#{bookBean.defaultDataModel}" var="g" onRowMouseOver="this.style.backgroundColor='#edf2f6';" onRowMouseOut="this.style.backgroundColor='#ffffff';"> <f:facet name="header"> <rich:columnGroup> <h:column> <h:outputText value="货物编号" /> </h:column> <h:column> <h:outputText value="货物品名" /> </h:column> <h:column> <h:outputText value="型号" /> </h:column> <h:column> <h:outputText value="包装" /> </h:column> </rich:columnGroup> </f:facet> <h:column> <h:outputText value="#{g.fcustomerID}" /> </h:column> <h:column> <h:outputText value="#{g.fgoodsName}" /> </h:column> <h:column> <h:outputText value="#{g.fgoodsModel}" /> </h:column> <h:column> <h:outputText value="#{g.fgoodPackage}" /> </h:column> <f:facet name="footer"> <rich:datascroller for="bookList" styleClass="ds" renderIfSinglePage="true" maxPages="5" page="#{bookBean.scrollerPage}" /> </f:facet> </rich:dataTable> </div> </h:form> </f:view>