package com.jsecode.util.pagination;

import java.util.ArrayList;

import java.util.List;

import javax.faces.context.FacesContext;

import javax.faces.model.DataModel;

import com.gcoresoft.jsfdemo.bean.CarBeanDAO;

public class DataScrollerList extends BasePagedBackingBean


{

CarBeanDAO dao = null;

public DataScrollerList()

{
dao = new CarBeanDAO();
}

public int getTotalCount()

{

int totalCount = 0;

totalCount = dao.getTotalCount();

return totalCount;

}


/** *//**
*
* 在DataScrollerList这个 Backing Bean中加一些东西,<br>
*
* 调用业务逻辑,并将数据交给PagedListDataModel,来帮我们完成最后的分页工作。
*
*/

public DataPage getDataPage(int startRow, int pageSize)

{

DataPage dataPage = dao.getDataPage(startRow, pageSize);

return dataPage;

}

}

JSP页面:
<f:view>
<h:form>
<rich:dataTable id="carList" width="483" rows="12" columnClasses="col"
value="#{scrollerList.dataModel}" var="car">
<f:facet name="header">
<rich:columnGroup>
<h:column>
<h:outputText styleClass="headerText" value="Name" />
</h:column>
<h:column>
<h:outputText styleClass="headerText" value="Decription" />
</h:column>
<h:column>
<h:outputText styleClass="headerText" value="Base Price" />
</h:column>
<h:column>
<h:outputText styleClass="headerText" value="Time" />
</h:column>
<h:column>
<h:outputText styleClass="headerText" value="操作操作" />
</h:column>
</rich:columnGroup>
</f:facet>
<h:column>
<h:outputText value="#{car.name}" />
</h:column>
<h:column>
<h:outputText value="#{car.description}" />
</h:column>
<h:column>
<h:outputText value="#{car.baseprice}" />
</h:column>
<h:column>
<h:outputText value="#{car.timestamp}" />
</h:column>
<h:column>
<h:commandLink action="#{user.delete}" value="删除" >
<f:param name="id" value="#{car.id}"/>
</h:commandLink>
</h:column>
</rich:dataTable>
<rich:datascroller for="carList" id="dc1"
style="width:483px" page="#{user.scrollerPage}"/>
</h:form>
</f:view>
faces-config.xml:
<managed-bean>
<managed-bean-name>scrollerList</managed-bean-name>
<managed-bean-class>com.jsecode.util.pagination.DataScrollerList</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
DataPage.java:
package com.jsecode.util.pagination;

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;

}

}

PagedListDataModel.java:
package com.jsecode.util.pagination;

import javax.faces.model.DataModel;


/** *//**

* A special type of JSF DataModel to allow a datatable and datascroller to page

* through a large set of data without having to hold the entire set of data in

* memory at once.

* <p>

* Any time a managed bean wants to avoid holding an entire dataset, the managed

* bean should declare an inner class which extends this class and implements

* the fetchData method. This method is called as needed when the table requires

* data that isn\'t available in the current data page held by this object.

* <p>

* This does require the managed bean (and in general the business method that

* the managed bean uses) to provide the data wrapped in a DataPage object that

* provides info on the full size of the dataset.

*/


/** *//**
*
* 这个类里面的方法被dataTable调用顺序为:<br>
*
* 1.构造函数public PagedListDataModel(int pageSize) <br>
*
* 2.getRowCount()<br>
*
* 3.setRowIndex()<br>
*
* 4.public boolean isRowAvailable()<br>
*
* 5.public Object getRowData()
*
*/

public abstract class PagedListDataModel extends DataModel


{

int pageSize;

int rowIndex;

private int rowCount = -1;

DataPage page;


/** *//**
*
* Create a datamodel that pages through the data showing the specified
*
* number of rows on each page.
*
*/

public PagedListDataModel(int pageSize)

{

super();

this.pageSize = pageSize;

this.rowIndex = -1;

this.page = null;

}


/** *//**
*
* Not used in this class; data is fetched via a callback to the fetchData
*
* method rather than by explicitly assigning a list.
*
*/

public void setWrappedData(Object o)

{


if ( o instanceof DataPage )
{
this.page = (DataPage) o;

} else
{
throw new UnsupportedOperationException("setWrappedData");
}

}

public int getRowIndex()

{

return rowIndex;

}


/** *//**
*
* Specify what the "current row" within the dataset is. Note that the
*
* UIData component will repeatedly call this method followed by getRowData
*
* to obtain the objects to render in the table.
*
*/

public void setRowIndex(int index)

{

rowIndex = index;

}


/** *//**
*
* Return the total number of rows of data available (not just the number of
*
* rows in the current page!).
*
*/

public int getRowCount()

{


if ( rowCount < 0 )
{
rowCount = fetchRowCount();
}

return rowCount;

}


/** *//**
*
* Return a DataPage object; if one is not currently available then fetch
*
* one. Note that this doesn\'t ensure that the datapage returned includes
*
* the current rowIndex row; see getRowData.
*
*/

private DataPage getPage(String name)

{


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;

}


/** *//** */


/** *//**
*
* Return the object corresponding to the current rowIndex. If the DataPage
*
* object currently cached doesn\'t include that index then fetchPage is
*
* called to retrieve the appropriate page.
*
*/

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);

rowCount = page.getDatasetSize();//

}

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);

rowCount = page.getDatasetSize();

startRow = page.getStartRow();


} else if ( rowIndex >= endRow )
{ // 向后取数据

page = fetchPage(rowIndex, pageSize);

rowCount = page.getDatasetSize();//

startRow = page.getStartRow();

}

return page.getData().get(rowIndex - startRow);

}

public Object getWrappedData()

{

return page.getData();

}


/** *//** */


/** *//**
*
* Return true if the rowIndex value is currently set to a value that
*
* matches some element in the dataset. Note that it may match a row that is
*
* not in the currently cached DataPage; if so then when getRowData is
*
* called the required DataPage will be fetched by calling fetchData.
*
*/

public boolean isRowAvailable()

{

DataPage page = getPage("isRowAvailable");


if ( page == null )
{

return false;

}

int rowIndex = getRowIndex();


if ( rowIndex < 0 )
{

return false;


} else if ( rowIndex >= page.getDatasetSize() )
{

return false;


} else
{

return true;

}

}


/** *//** */


/** *//**
*
* Method which must be implemented in cooperation with the managed bean
*
* class to fetch data on demand.
*
*/

public abstract DataPage fetchPage(int startRow, int pageSize);

public abstract int fetchRowCount();

}

BasePagedBackingBean:
package com.jsecode.util.pagination;

import javax.faces.model.DataModel;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public abstract class BasePagedBackingBean


{

protected abstract DataPage getDataPage(int startRow, int pageSize);

public abstract int getTotalCount();

private DataModel dataModel;

private int i = 0;

// 为什么getDataModel这个方法要调用两次?非常不解啊
public DataModel getDataModel()

{


if ( dataModel == null )
{
dataModel = new LocalDataModel(10);
}

return dataModel;

}

public Object getBean(String beanName)

{

return null;
}

private class LocalDataModel extends PagedListDataModel

{

public LocalDataModel(int pageSize)

{

super(pageSize);

}

public int fetchRowCount()

{

return getTotalCount();

}

public DataPage fetchPage(int startRow, int pageSize)

{

// call enclosing managed bean method to fetch the data

return getDataPage(startRow, pageSize);

}

}

}

DataScrollerList.java:
package com.jsecode.util.pagination;

import java.util.ArrayList;

import java.util.List;

import javax.faces.context.FacesContext;

import javax.faces.model.DataModel;

import com.gcoresoft.jsfdemo.bean.CarBeanDAO;

public class DataScrollerList extends BasePagedBackingBean


{

CarBeanDAO dao = null;

public DataScrollerList()

{
dao = new CarBeanDAO();
}

public int getTotalCount()

{

int totalCount = 0;

totalCount = dao.getTotalCount();

return totalCount;

}


/** *//**
*
* 在DataScrollerList这个 Backing Bean中加一些东西,<br>
*
* 调用业务逻辑,并将数据交给PagedListDataModel,来帮我们完成最后的分页工作。
*
*/

public DataPage getDataPage(int startRow, int pageSize)

{

DataPage dataPage = dao.getDataPage(startRow, pageSize);

return dataPage;

}

}

每个DAO都实现了这个接口:
package com.gcoresoft.jsfdemo.bean;

import java.util.List;

import com.jsecode.util.pagination.DataPage;


/** *//**
* @author TiGERTiAN tigertian@gmail.com
* @version
* Oct 29, 2008 9:46:55 AM
*/

public interface Pagination


{
public int getTotalCount();
public DataPage getDataPage(int startRow, int pageSize);
public List getPagedList(int startRow, int pageSize);
}

DAO中的相关代码:
public DataPage getDataPage(int startRow, int pageSize)

{
// TODO Auto-generated method stub
return new DataPage(getTotalCount(), startRow, getPagedList(startRow, pageSize));
}

public int getTotalCount()

{
Query q = EntityManagerHelper.createQuery("select count(*) from CarBean");
System.out.println("row count = " + q.getSingleResult().toString());
return Integer.parseInt(q.getSingleResult().toString());
}

public List getPagedList(int startRow, int pageSize)

{
String sql = "from CarBean model order by model.id desc";

Query query = EntityManagerHelper.createQuery(sql);

query.setFirstResult(startRow);

query.setMaxResults(pageSize);

List list = query.getResultList();
System.out.println("current row count = " + list.size());
return list;

}
---------------------------------------------------------
专注移动开发
Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
posted on 2008-10-29 10:58
TiGERTiAN 阅读(2835)
评论(3) 编辑 收藏 所属分类:
Java 、
JSF