好久沒(méi)有寫點(diǎn)東西了,這次想把JSF中的分頁(yè)系列文章再擴(kuò)充一點(diǎn),說(shuō)明一下查詢和分頁(yè)結(jié)合的情況,當(dāng)我們把查詢條件和查詢結(jié)果放到一個(gè)頁(yè)面上時(shí),查詢還是非常容易實(shí)現(xiàn)的,甚至不需要我們手工去從數(shù)據(jù)庫(kù)中查詢。
在本系列文章中的第二篇中,介紹了一種 Load On Demand的方式,我們?cè)谶@里需要繼續(xù)利用這種方式,并對(duì)其做一些小小的擴(kuò)展。這里我們使用 Hibernate3 作為持久化方案。
簡(jiǎn)單的介紹一下應(yīng)用情景,一個(gè)系統(tǒng)中包含了一些 Customer 的信息,我們需要對(duì)其進(jìn)行查詢并對(duì)查詢結(jié)果進(jìn)行分頁(yè)。
首先處理?xiàng)l件查詢的情況,通常會(huì)根據(jù) VO 中的字段進(jìn)行 like 型查詢,有時(shí)候時(shí)間或數(shù)字之類的會(huì)使用Between查詢,因?yàn)椴樵儣l件一般不會(huì)很復(fù)雜,在這里,使用 Hibernate3 中的 Criteria 查詢來(lái)處理這樣的情況,我們把所有的查詢條件通過(guò) Customer 這個(gè) VO 傳進(jìn)來(lái),然后只對(duì)非空字段進(jìn)行 like 查詢,我們用到這樣的方法。
public
?List?queryByConditions(Customer?customer,?
int
?startRow,?
int
?pageSize)
{
?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);
}
另外對(duì)應(yīng)的一個(gè)count方法略去,只需要在前面加入一個(gè)
criteria.setProjection(Projections.count("customerId"));
因?yàn)榭紤]到以后的擴(kuò)展,使用了一個(gè)Utils方法,QueryUtils.getCriteriaParam方法
public
?
static
?
final
?SimpleExpression?getCriteriaParam(String?name,?String?param)
{
?
return
?Expression.like(name,?
"
%
"
?
+
?param?
+
?
"
%
"
);
}
我們可以很容易的在 Backing Bean 上通過(guò) Service 層拿到這個(gè)查詢結(jié)果的 List 和 Count 值,相關(guān)的getDatePage方法如下。
如果你不了解這個(gè) getDataPage 方法的含義,請(qǐng)仔細(xì)閱讀“在JSF中實(shí)現(xiàn)分頁(yè)(二)”一文,并仔細(xì)思考該方法的含義。
protected
?DataPage?getDataPage(
int
?startRow,?
int
?pageSize)
{
?List?queryCustomerList?
=
?customerService.queryCustomer(customer,?
this
.startRow,?
this
.getPageSize());
?
int
?dataSetSize?
=
?customerService.countQueryCustomer(customer);
?
return
?
new
?DataPage(dataSetSize,?startRow,?queryCustomerList);
}
在同一個(gè) Backing Bean 中,我們放了一個(gè)存放查詢條件的VO - Customer,并在頁(yè)面中使用<t:saveState>保存其狀態(tài),使其查詢條件不會(huì)隨著翻頁(yè)而丟失。
<t:saveState value="#{customerListBean.customer}"/>
在頁(yè)面中,我們把所有的查詢條件都放到該 VO 中,在 getDataPage 方法中就會(huì)在適當(dāng)?shù)臅r(shí)候調(diào)用新的查詢條件來(lái)查詢新的數(shù)據(jù),這一切都不需要我們動(dòng)手的。
在 Backing Bean 中有這樣的一個(gè)方法:
public
?String?query()
{
?dataModel.setWrappedData(getDataPage(
0
,?getPageSize()));
?
return
?
"
success
"
;
}
只是把數(shù)據(jù)清空,并強(qiáng)制 PagedListDataModel 讀取數(shù)據(jù),然后我們返回相同的頁(yè)面,這個(gè)時(shí)候,系統(tǒng)按照用戶輸入的查詢條件拿到查詢結(jié)果以后,返回同一頁(yè)面,該頁(yè)面中的使用 LocalDataModel 的那個(gè) DataTable 就會(huì)把結(jié)果顯示出來(lái)。
請(qǐng)注意,這里 LocalDataModel 和 Customer 都在同一個(gè) Backing Bean 中。
是不是覺(jué)得很簡(jiǎn)單呢,一切都?xì)w功于 getDataPage 這個(gè)方法,我們幾乎不需要做什么額外的操作就可以達(dá)到我們的目的。
因?yàn)樵摲椒ㄔ谝粋€(gè)商業(yè)項(xiàng)目中使用,代碼不便公布,只能把里面的一些代碼抽取出來(lái),零零碎碎的拿給大家看,如果大家有什么疑問(wèn)的話,可以在論壇上提出來(lái),我會(huì)盡力解答的,另外這個(gè)方法也會(huì)在空閑的時(shí)候 Merge 到 MyPSP 項(xiàng)目中去。
posted on 2006-03-28 19:12
steady 閱讀(6687)
評(píng)論(5) 編輯 收藏 所屬分類:
JSF & Myfaces