好久没有写点东西了,这次想把JSF中的分页系列文章再扩充一点,说明一下查询和分页结合的情况,当我们把查询条件和查询结果放到一个页面上时,查询还是非常容易实现的,甚至不需要我们手工去从数据库中查询。
在本系列文章中的第二篇中,介绍了一种 Load On Demand的方式,我们在这里需要继续利用这种方式,并对其做一些小小的扩展。这里我们使用 Hibernate3 作为持久化方案。
简单的介绍一下应用情景,一个系统中包含了一些 Customer 的信息,我们需要对其进行查询并对查询结果进行分页。
首先处理条件查询的情况,通常会根据 VO 中的字段进行 like 型查询,有时候时间或数字之类的会使用Between查询,因为查询条件一般不会很复杂,在这里,使用 Hibernate3 中的 Criteria 查询来处理这样的情况,我们把所有的查询条件通过 Customer 这个 VO 传进来,然后只对非空字段进行 like 查询,我们用到这样的方法。
{
Criteria criteria = getSession().createCriteria(Customer. class );
if ( ! StringUtils.isEmpty(customer.getCustomerName()))
{
criteria.add(QueryUtils.getCriteriaParam( " customerName " , customer.getCustomerName()));
}
if ( ! StringUtils.isEmpty(customer.getAddress()))
{
criteria.add(QueryUtils.getCriteriaParam( " address " , customer.getAddress()));
}
if ( ! StringUtils.isEmpty(customer.getFax()))
{
criteria.add(QueryUtils.getCriteriaParam( " fax " , customer.getFax()));
}
return criteriaPagedList(criteria, startRow, pageSize);
}
另外对应的一个count方法略去,只需要在前面加入一个
criteria.setProjection(Projections.count("customerId"));
因为考虑到以后的扩展,使用了一个Utils方法,QueryUtils.getCriteriaParam方法
{
return Expression.like(name, " % " + param + " % " );
}
我们可以很容易的在 Backing Bean 上通过 Service 层拿到这个查询结果的 List 和 Count 值,相关的getDatePage方法如下。
如果你不了解这个 getDataPage 方法的含义,请仔细阅读“在JSF中实现分页(二)”一文,并仔细思考该方法的含义。
{
List queryCustomerList = customerService.queryCustomer(customer, this .startRow, this .getPageSize());
int dataSetSize = customerService.countQueryCustomer(customer);
return new DataPage(dataSetSize, startRow, queryCustomerList);
}
在同一个 Backing Bean 中,我们放了一个存放查询条件的VO - Customer,并在页面中使用<t:saveState>保存其状态,使其查询条件不会随着翻页而丢失。
<t:saveState value="#{customerListBean.customer}"/>
在页面中,我们把所有的查询条件都放到该 VO 中,在 getDataPage 方法中就会在适当的时候调用新的查询条件来查询新的数据,这一切都不需要我们动手的。
在 Backing Bean 中有这样的一个方法:
{
dataModel.setWrappedData(getDataPage( 0 , getPageSize()));
return " success " ;
}
只是把数据清空,并强制 PagedListDataModel 读取数据,然后我们返回相同的页面,这个时候,系统按照用户输入的查询条件拿到查询结果以后,返回同一页面,该页面中的使用 LocalDataModel 的那个 DataTable 就会把结果显示出来。
请注意,这里 LocalDataModel 和 Customer 都在同一个 Backing Bean 中。
是不是觉得很简单呢,一切都归功于 getDataPage 这个方法,我们几乎不需要做什么额外的操作就可以达到我们的目的。
因为该方法在一个商业项目中使用,代码不便公布,只能把里面的一些代码抽取出来,零零碎碎的拿给大家看,如果大家有什么疑问的话,可以在论坛上提出来,我会尽力解答的,另外这个方法也会在空闲的时候 Merge 到 MyPSP 项目中去。