好久沒有寫點東西了,這次想把JSF中的分頁系列文章再擴充一點,說明一下查詢和分頁結(jié)合的情況,當我們把查詢條件和查詢結(jié)果放到一個頁面上時,查詢還是非常容易實現(xiàn)的,甚至不需要我們手工去從數(shù)據(jù)庫中查詢。
在本系列文章中的第二篇中,介紹了一種 Load On Demand的方式,我們在這里需要繼續(xù)利用這種方式,并對其做一些小小的擴展。這里我們使用 Hibernate3 作為持久化方案。
簡單的介紹一下應(yīng)用情景,一個系統(tǒng)中包含了一些 Customer 的信息,我們需要對其進行查詢并對查詢結(jié)果進行分頁。
首先處理條件查詢的情況,通常會根據(jù) VO 中的字段進行 like 型查詢,有時候時間或數(shù)字之類的會使用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);
}
另外對應(yīng)的一個count方法略去,只需要在前面加入一個
criteria.setProjection(Projections.count("customerId"));
因為考慮到以后的擴展,使用了一個Utils方法,QueryUtils.getCriteriaParam方法
{
? return ?Expression.like(name,? " % " ? + ?param? + ? " % " );
}
我們可以很容易的在 Backing Bean 上通過 Service 層拿到這個查詢結(jié)果的 List 和 Count 值,相關(guān)的getDatePage方法如下。
如果你不了解這個 getDataPage 方法的含義,請仔細閱讀“在JSF中實現(xiàn)分頁(二)”一文,并仔細思考該方法的含義。
{
?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ài),使其查詢條件不會隨著翻頁而丟失。
<t:saveState value="#{customerListBean.customer}"/>
在頁面中,我們把所有的查詢條件都放到該 VO 中,在 getDataPage 方法中就會在適當?shù)臅r候調(diào)用新的查詢條件來查詢新的數(shù)據(jù),這一切都不需要我們動手的。
在 Backing Bean 中有這樣的一個方法:
{
?dataModel.setWrappedData(getDataPage( 0 ,?getPageSize()));
? return ? " success " ;
}
只是把數(shù)據(jù)清空,并強制 PagedListDataModel 讀取數(shù)據(jù),然后我們返回相同的頁面,這個時候,系統(tǒng)按照用戶輸入的查詢條件拿到查詢結(jié)果以后,返回同一頁面,該頁面中的使用 LocalDataModel 的那個 DataTable 就會把結(jié)果顯示出來。
請注意,這里 LocalDataModel 和 Customer 都在同一個 Backing Bean 中。
是不是覺得很簡單呢,一切都歸功于 getDataPage 這個方法,我們幾乎不需要做什么額外的操作就可以達到我們的目的。
因為該方法在一個商業(yè)項目中使用,代碼不便公布,只能把里面的一些代碼抽取出來,零零碎碎的拿給大家看,如果大家有什么疑問的話,可以在論壇上提出來,我會盡力解答的,另外這個方法也會在空閑的時候 Merge 到 MyPSP 項目中去。