Hibernate3 提供了DetachedCriteria,使得我们可以在Web层构造 4`6< {
dXDXRY.FMQ
detachedCriteria,然后调用业务层Bean,进行动态条件查询,根 ?f f
[$ab
-`g J
据这一功能,我设计了通用的抽象Bean基类和分页类支持,代码来 2;h+;G
MU*It"@}2
自于Quake Wang的javaeye-core包的相应类,然后又做了很多修改 cPSti
:-U53}Iy
。 tStJ2-5*t
]6q*)q:`
分页支持类: St_Sl:m$
1[px`%DR~
java代码: >-eS&rma
SNN#$8\
}9
?y'6l
package com.javaeye.common.util; ]An_5J
xjE7DCmA
import java.util.List; _V&x`ks
*cPN\Iu.W
publicclass PaginationSupport { yduuFK
wZ
O@J|
publicfinalstaticint PAGESIZE = 30; yE<,Z%J[n
oLd:3,p}
privateint pageSize = PAGESIZE; X= SG
8M~u_`6
privateList items; vU7&'ca
EFeAr@nj
privateint totalCount; A^t"MYX@
88#N~j~P
privateint[] indexes = newint[0]; B9AbKK$`
b70AJe=
privateint startIndex = 0; vLr&ay!w
-GFwFkWm
public PaginationSupport(List items, int l-XnB
ZDfS0]0F
totalCount){ 0xLkyt0
setPageSize(PAGESIZE); d0TgqO{
setTotalCount(totalCount); *0lt$F$~b
setItems(items); X&/(x
setStartIndex(0); !%X>rGkc
} #U:0/4P(
b13nE.
public PaginationSupport(List items, int YN$`y1V
G$|G w
totalCount, int startIndex){ X:DMT>5k
setPageSize(PAGESIZE); @f\
X4!e*y
setTotalCount(totalCount); :bI,rEW#_
setItems(items); " xlJs93c
setStartIndex(startIndex); M.X}K7Z_/
} lu3Q, W
=#jTo|~u4o
public PaginationSupport(List items, int [+_\z',u
} mgVC
totalCount, int pageSize, int startIndex){ aE}=^%D
setPageSize(pageSize); \;iG{}(
setTotalCount(totalCount); KLON;
setItems(items); Z`|> tbOfZ
setStartIndex(startIndex); 2UQN*_
} ,=yOek}
O0->sR
publicList getItems(){ "--/v. Cs
return items; d4Ixuux<3
} S3nB:$_-;
]!q
}|bP
publicvoid setItems(List items){ /\nJ
this.items = items; .x]'eq}
} mSy|&(l
AwtIWH*e
publicint getPageSize(){ kja4!_d
return pageSize; 6V+V
zDo
} =P1RdyP
ShsJ_/C2
publicvoid setPageSize(int pageSize){ }F~f&<GX6
this.pageSize = pageSize; i[mC3ghM6,
} !'+\]eA
<##|311o
publicint getTotalCount(){ fi5YMYd1
return totalCount; ux%&lff
} _xa}B,H
2-QuT"Gkd
publicvoid setTotalCount(int totalCount){ {_rZRyr
if(totalCount > 0){ 'W}~)+zK
this.totalCount = totalCount; g9M')8a n
int count = totalCount /
b$PT_!d
C3]\$
pageSize; }klE0<W|5\
if(totalCount % pageSize > 0) N `J:^,H
count++; L00Sp#$\
indexes = newint[count]; 2*N&q|ED
for(int i = 0; i < count; i++){ ys:1Z\$P
indexes = pageSize * 4F}g(
-/@|2!d
i; MX"A@p~H
} z]'|nX
}else{ -$'~;O3s
this.totalCount = 0; [8{_i?wY
} U+(Z#b(Q
} (N)r#"FV
1'(_>S5CG
publicint[] getIndexes(){ .`:oP&9r
return indexes; f+Pg1Q0zI
} ZD$-V3e`
^vYVl{$bT
publicvoid setIndexes(int[] indexes){ 3WQRN_
this.indexes = indexes; w:~nw;.T
} MtMvpHk
xC=
y^-
1
publicint getStartIndex(){ 3L'en
return startIndex; >lUBt5gU
} #|)JD@;Q
t-3v1cv"
publicvoid setStartIndex(int startIndex){ yg]suU<z]
if(totalCount <= 0) @m*&c* r
this.startIndex = 0; 0sq=5 BnO
elseif(startIndex >= totalCount) )pkhir06t
this.startIndex = indexes rD:gN%B=
vo:52tCk}m
[indexes.length - 1]; Km|9Too
elseif(startIndex < 0) Zm"!E6`69
this.startIndex = 0; h;cB_6vt
else{ n's2/9x
this.startIndex = indexes x@{G(W:W
.6lY*LI
[startIndex / pageSize]; Y&ct+w]%
} MAm1w'ol"
} oO! 1
C:|q'"F
publicint getNextIndex(){ j1'xp`jgv
int nextIndex = getStartIndex() + EuR!yD
1puEP*P
pageSize; B:R7[G;1
if(nextIndex >= totalCount) _ Yb
Eo+
return getStartIndex(); =:t@;y
else +G3nn!gl4
return nextIndex; Pn'QOVy
} l8hvq(,{
.FfwY 'V
publicint getPreviousIndex(){ /K2.V@T
int previousIndex = getStartIndex() - ;o~+2Fir
ae9k[=-
pageSize; `dG.L
if(previousIndex < 0) <> &e/
return0; J4Q)`Y\~
else .ruz l(6
return previousIndex; rw}5nv
} a}[=_vb}K
:IP;FrcMP
} $S($97IU=
g:~?U*f-
ZNL;8sI?>
f)u*Q!BDD
抽象业务类 %x cM_|AyR
java代码: zm;*:]S
s+y'<88
(Fbm9(q$d
/** ne!j%9Ar
* Created on 2005-7-12 7gZVg@
*/ q/ d5P
package com.javaeye.common.business; 1pYmtr
D@sx`H(
import java.io.Serializable; `JY>v io
import java.util.List; |p=.Gg=2
b]tA2~e
import org.hibernate.Criteria; n]6}yJJo
import org.hibernate.HibernateException; @4 Os?_gJ\
import org.hibernate.Session; E7Gi6w~\
import org.hibernate.criterion.DetachedCriteria; %>I?'y^
import org.hibernate.criterion.Projections; >[E|p6jgT
import ei|*s+OZu
"c !oOaA
org.springframework.orm.hibernate3.HibernateCallback; kMJQeo79
import (>+k 3
5tgILxSK
org.springframework.orm.hibernate3.support.HibernateDaoS (DELxE
4$q)e<-
upport; M'>D[5;N~
\M'bY:
import com.javaeye.common.util.PaginationSupport; V{AH\IV-
r0hta)xa
public abstract class AbstractManager extends r[UyI3(i^
+ hyWo]nW0
HibernateDaoSupport { yp^[]Mz=
J^F(]
privateboolean cacheQueries = false; :xAe<Pq
Z)6nu)
privateString queryCacheRegion; \^;|S
gn[$;*932z
publicvoid setCacheQueries(boolean sBuq
SG+i\yu$h0
cacheQueries){ q.,p6D
this.cacheQueries = cacheQueries; \/x)BE,
} &[W3e3Asra
*k@0:a(>
publicvoid setQueryCacheRegion(String 0]2B-o"kI
LBbo.KxAe3
queryCacheRegion){ $@:>7Y"
this.queryCacheRegion = ]` &[Se d
D"(3VIglq
queryCacheRegion; ai;gca_P#
} Vx7Dl{?{'
{Y@-*pL]
publicvoid save(finalObject entity){ hI>rtaY_
getHibernateTemplate().save(entity); B;D:9K
} hk lO:,`
nX.s h
publicvoid persist(finalObject entity){ z7.C\l
getHibernateTemplate().save(entity); v{rK_jq
} gQk#l\w_
Z,8+@
publicvoid update(finalObject entity){ Y+"hu2aPkY
getHibernateTemplate().update(entity); [ilv/V<
} d6d(?"
x9o^9QJh
publicvoid delete(finalObject entity){ xJH9qc ME
getHibernateTemplate().delete(entity); @cTZ`bg
} !+|N<`
l~Wk07r3
publicObject load(finalClass entity, GHgEbiY:
Y9co?!J 5M
finalSerializable id){ q:~`7I
return getHibernateTemplate().load }96/:
;:k
+{Vwz
(entity, id); sKB-7
} :9rhv{6Wp
ubN"(F:!-S
publicObject get(finalClass entity, s>M~g,xTU
7L~ zI>2
finalSerializable id){ h7W%}6Cqkw
return getHibernateTemplate().get f'i8Mm4IL
]stLC; nI
(entity, id); g`5`KU|
} A*26'
+VpE-X=T
publicList findAll(finalClass entity){ )r6SGlE[Y
return getHibernateTemplate().find("from {, *Y
p`l[cVQ<
" + entity.getName());
VjB`~
} D'sboOY
tx1m36a"
publicList findByNamedQuery(finalString 5 dNf$a0E
7^t(RNq
namedQuery){ neY=:9
return getHibernateTemplate zs]/Y2
LG@c)H74
().findByNamedQuery(namedQuery); L};;o+5uJD
} ,w/mk$v
nXeK,C
publicList findByNamedQuery(finalString query, ao";5m
O]%m{afM
finalObject parameter){ ";Ig%]
return getHibernateTemplate FnQ_=b
xV 1Z&l
().findByNamedQuery(query, parameter); )Fr;'JYC1S
} ?o(X0
b\Xu1>
publicList findByNamedQuery(finalString query, uA/.4 b
*ZSp9g"Z
finalObject[] parameters){ 7%"\DLA
return getHibernateTemplate uSQ>oi]
@Jn:!8U0
().findByNamedQuery(query, parameters); w KMk|y>
} Y /ac}q
7pI\`*7b
publicList find(finalString query){ LX?r=_\
return getHibernateTemplate().find 0*:hm%g
}v$=mLy
(query); NUNn[c
} , ZP3F+XKb
O\8|niW|
publicList find(finalString query, finalObject F?,&y)ri
!%\To(r[
parameter){ rs<&x(=Hv
return getHibernateTemplate().find 16> >4U:Y
*I1W+W`G
(query, parameter); e%v4,8
} |e[0Qo@
xjbyI_D
public PaginationSupport findPageByCriteria
0S5C7df
_}9R}
(final DetachedCriteria detachedCriteria){ >=W#z
return findPageByCriteria *=If1qZs
sriq(A
(detachedCriteria, PaginationSupport.PAGESIZE, 0); ^FMa8;'o
} .rB;zA;4S)
]3y5b9DuW
public PaginationSupport findPageByCriteria &MQt2aL
*u4X<oBS*
(final DetachedCriteria detachedCriteria, finalint &eS70hq
6'*Uo:]
startIndex){ /uz5V/i0
return findPageByCriteria ?N?pe}
= SJF\Z
(detachedCriteria, PaginationSupport.PAGESIZE, %iS]+Sa.K
+2fJ
startIndex); @[kM1:G-F{
} NlEWm8u
pD6g+Taj
public PaginationSupport findPageByCriteria m^x\@!N:(
DfzUGX
(final DetachedCriteria detachedCriteria, finalint l5OV!<7~X
8EEQV} 4
pageSize, -+_aL4.
finalint startIndex){
-Fc#
return(PaginationSupport) 4kF .
m'"VuH?^
getHibernateTemplate().execute(new HibernateCallback(){ p'!,F; xX
publicObject doInHibernate s]8J+8
<uO
nzJi)A./
(Session session)throws HibernateException { `0XbV A
Criteria criteria = V>uW|6
fX$4TPy(h
detachedCriteria.getExecutableCriteria(session); -qP[$Q
int totalCount = fQ_8{=<-&X
lnSE+YJ>
((Integer) criteria.setProjection(Projections.rowCount X6*y/KGN
&r5%WRzpYT
()).uniqueResult()).intValue(); mL5f_Fb+
criteria.setProjection 8Y~T$Yj^
>upUY(3&
(null); PyxN _agf
List items =
mFoK76
DSZhl-uGM
criteria.setFirstResult(startIndex).setMaxResults y$9t!cx
dB/I2uGl>
(pageSize).list(); safS>wM]
PaginationSupport ps = ~I|R}hS
rZQHB[^3
new PaginationSupport(items, totalCount, pageSize, lbU+a$
2LH;d`H[0
startIndex); e.ym7L]$O
return ps; Wy>\KrA1
} SA n=9MG
}, true); zp-~'kIJ
} K}3"K C
'"\Mjz)/
public List findAllByCriteria(final !,!tNs1 K
by<@Zwtf
DetachedCriteria detachedCriteria){ HF[%/Tu
return(List) getHibernateTemplate "57G@NC{n
x2c*k$<p
().execute(new HibernateCallback(){ A?k,}~
publicObject doInHibernate 'wlP` 7&Tn
+9rbQ?'
(Session session)throws HibernateException { 6U9Fa=%>}
Criteria criteria = X&oy.Roo
-vfu0XI~
detachedCriteria.getExecutableCriteria(session); mf[79:90^
return criteria.list(); o?
"@9O?
} 9}$dwl(
}, true); 5d{Ggg{s
} pcTXTy 28
@wJa33QT
public int getCountByCriteria(final #|h8u`
8B+^vF
DetachedCriteria detachedCriteria){ _H<OfAO
Integer count = (Integer) t
U=b~
!rGI),
getHibernateTemplate().execute(new HibernateCallback(){ vUx$[/<
publicObject doInHibernate T\CQ
@Hdg-f>y]
(Session session)throws HibernateException { (`/i1#nR
Criteria criteria = Z@O
e}\.$
6v)eM=
detachedCriteria.getExecutableCriteria(session); ^F9zS`Yz2
return R*eM 1
2#}IGZ`Yp/
criteria.setProjection(Projections.rowCount qA/3uA!z
b+apN ph
()).uniqueResult(); `^k<.O
} MtTHKp
}, true); TsW6 w
return count.intValue(); _?LI0iIFx
} luog_;{h+
} 3"D00~
~M1%,]
2]f.mq_PD
2+cicBD
lS*.?4zX
GhA~Pj ZS
用户在web层构造查询条件detachedCriteria,和可选的 uxiX"0)g>
o;I86dI6C
startIndex,调用业务bean的相应findByCriteria方法,返回一个 iGNKf|8{
xmd$Jol^
PaginationSupport的实例ps。 {\Y,UANZ
B#n}y
ps.getItems()得到已分页好的结果集 #wuE30d
ps.getIndexes()得到分页索引的数组 g~u!,Zc
ps.getTotalCount()得到总结果数 ]r5Xp#q2
ps.getStartIndex()当前分页索引 1K',Vw_
ps.getNextIndex()下一页索引 iqP0=(^m
ps.getPreviousIndex()上一页索引 xl=|]8w
)PNk
O3
90D.G_45
F$p,xFH#
}gaKO 5
8GQs9
U<byR!qLie
连续看了两篇robbin有关DetachedCriteria的介绍,感觉真的不错 (7!(e
,
|.nWy"L
,尤其是上面的示例代码,让我着实觉得该对我原来的分页查询做 {'aqOlw3<j
vjS7nR"T
一下代码重构了。 g&5VorGx
0k]N%!U
我把原本我的做法也提供出来供大家讨论吧: 8#-}3~l[
`P*j~ZLlXN
首先,为了实现分页查询,我封装了一个Page类: /^ 7
9|$E
java代码: kIo?<=F8T
e$I:[>
-q|M=6gOs
/*Created on 2005-4-14*/ )+R3C%
package org.flyware.util.page; HXo'^^}q;
5|z[%x~f
/** $7g(-W
* @author Joa 6
VDF@V$E
* 'o9V0#$!
*/ Y:BrAa[
publicclass Page { 24l9/v'
K*RRbtb
/** imply if the page has previous page */ FQ^uX]<3j
privateboolean hasPrePage; ^S$w,
5OE?;PJ(
/** imply if the page has next page */ ?q`mr_x%?
privateboolean hasNextPage; wO
NQlt
l]cQ7g5
/** the number of every page */ y+h=x4t
privateint everyPage; |9M
y>8k(
Q"uu&JC
/** the total page number */ aW5~z^I
privateint totalPage; i?9Lf
Pw1H)<X
/** the number of current page */ kp"cHJNx
privateint currentPage; =2'^:4Z
0Z(b/fdS
/** the begin index of the records by the current VlvDodV
ypVr"fWB
query */ _~"3
LB
privateint beginIndex; ?Kf@/jv
aS2
Y6
_:
x$"i
/** The default constructor */ e&nw&9vo
public Page(){ VNPdL
_95tgJ y
} r&;AG@N/
hw2Hn
/** construct the page by everyPage euK!JZ
* @param everyPage .quc i(D
* */ cd#TKmh7re
public Page(int everyPage){ PX'%)5:q;i
this.everyPage = everyPage; #UIg<:
} HN%ZN}
k5M(Ve
/** The whole constructor */ "m5ZZG#R`
public Page(boolean hasPrePage, boolean hasNextPage, {D8IA3w
CPG %*E*
g?wogCs5
int everyPage, int totalPage, 9G9lSj5>
int currentPage, int beginIndex){ '@bA_F(
this.hasPrePage = hasPrePage; u:|5jF
this.hasNextPage = hasNextPage; z/=v@@tj
this.everyPage = everyPage; !h\3cs`QU
this.totalPage = totalPage; ;?9~^,l
this.currentPage = currentPage; g!UM8I-$
this.beginIndex = beginIndex; J4; ".Y=
} dl4.jLY
L2%P
/** DTY=k
* @return %iNDRLR%I
* Returns the beginIndex. 3 -FNd~%
*/ `)fGw7J
{
publicint getBeginIndex(){ |v&&%>A2
return beginIndex; Ws(>}
qjy
} R_}(p2
@ ri.r1
/** Fk:(%ci
* @param beginIndex /uVB[Tk^
* The beginIndex to set. &0`L; 1R
*/ q ^?{6}sy
publicvoid setBeginIndex(int beginIndex){ R<)uvW_@
this.beginIndex = beginIndex; +Xk!)Ge5E*
} n:+MNr
_ev^5`>p/
/** I/l]Yv!
* @return Z8W<RiR
* Returns the currentPage. )_uK(UNZ5
*/ ~jaGf
publicint getCurrentPage(){ y;H
3g#
return currentPage; d8>D=Ve
} [+GG Wo
&!=3Fbn
/** g;pymz
* @param currentPage w pvaTHo
* The currentPage to set. |bh:x{h
*/ -e ya$C
publicvoid setCurrentPage(int currentPage){ 4^5s\f B
this.currentPage = currentPage; {+MMqJCa
} \BDNF<_
]_h"2|
/** Q=[&~^Y)
* @return FP$]D~DMo
* Returns the everyPage. ]!QeJ'BLM
*/ O-k(5Zb
publicint getEveryPage(){ Q1rwTg\
return everyPage; ]pt @
} S@_GjCpn
?@#<>7V
/** nC w1H kW
* @param everyPage ~kL":C>2
* The everyPage to set. G7yxCU(I\
*/ L2N/DB'{
publicvoid setEveryPage(int everyPage){ TBpW/wz/
this.everyPage = everyPage; S}+n\pyQ
} -4;u|0_
~(c<ioIf
/** "o1/gV
* @return & 3gni4@@
* Returns the hasNextPage. zy.Ok 49
*/ XjC+kH
publicboolean getHasNextPage(){ $]9d((u4
return hasNextPage; I'!KWpYJT
} C5m*pGImG
G100L}d"N
/** ;Wr$hDt^
* @param hasNextPage 5ZPl`[He
* The hasNextPage to set. )wC>Hq[mhW
*/ 3,GSBiK3}
publicvoid setHasNextPage(boolean hasNextPage){ 3k=q>~&@
this.hasNextPage = hasNextPage; Cpr}*A
} p|Ln;aYc
&EMm<(.]a
/** sU>*S$X8
* @return i9\Pks#l%
* Returns the hasPrePage. l4; LV7Ji
*/ 49CMRO,T
publicboolean getHasPrePage(){ *I~F7Z]|
return hasPrePage; a*=e 3nS
} ,}NG@JID
#2pgh?
/** sbRg=k&Ns
* @param hasPrePage =zsXa=<
* The hasPrePage to set. Ws=J)2q
*/ Z/64E^
publicvoid setHasPrePage(boolean hasPrePage){ P~~RK&+i
this.hasPrePage = hasPrePage; |(w x6H:
} k&Sg`'LG8
'h:4 Fzo<
/** Dv$xP)./
* @return Returns the totalPage. .EI/0"^
* J%nJO3,
*/ X/@Gx 4
publicint getTotalPage(){ X%;,r
2g
return totalPage; ;m\E9ple
} NY_Oo!)3
{r Gx*<e
/** !a0HF p$9
* @param totalPage U_w)*)F
* The totalPage to set. ': HV9]k
*/ mCg 5-E~;
publicvoid setTotalPage(int totalPage){ $XJe)
this.totalPage = totalPage; |/q *Fg[f
} L)Kn8
a+MC[aFr
} TiH(HW|:
$u>^A<TBN
U\ 51j
p{.EFa>H
?g9CeeH*
上面的这个Page类对象只是一个完整的Page描述,接下来我写了一 [}FP_Su$6
rt"\\sOlMB
个PageUtil,负责对Page对象进行构造: ,O2Uj3"
java代码: K\ZKVn
'Y[\[]3[8
-2f0CAh~
/*Created on 2005-4-14*/ ^E5Xpza
package org.flyware.util.page; k%hif8y
/H\ZCIu/7
import org.apache.commons.logging.Log; o'W &gkb9
import org.apache.commons.logging.LogFactory; $?0<rvGJ
1y
6H 2
/** \&SP7~-eq
* @author Joa M5D,YC3<
* 6MZfoR
*/ Q}G
publicclass PageUtil { O9!<L.X,%
]Dx5t&
privatestaticfinal Log logger = LogFactory.getLog z.7 UfLV9
_c`Gxt%
(PageUtil.class); P4s:wuJ^
64[j:t=N
/** 7pkc*@t
* Use the origin page to create a new page n`CmbM@@
* @param page D`Fl*Wc4H
* @param totalRecords u U\UULH0
* @return Q5baY\"9^
*/ pS51fF9
publicstatic Page createPage(Page page, int tk ~7>S
ZQ@^(64
totalRecords){ TMGZHOAt
return createPage(page.getEveryPage(), Dj?95Z,r
16xM?P
page.getCurrentPage(), totalRecords); pp/Cn4"w
} ,)%nLc
9-9`;Z
/** c_%vD~6W-
* the basic page utils not including exception b>G!K)MS3
C}wmoYikV
handler {DAwkJvb]
* @param everyPage Rg+V;C
C~
* @param currentPage xqLLoSte
* @param totalRecords d[jxU/.p;
* @return page 5'.j+{"
*/ i_ I`Y
publicstatic Page createPage(int everyPage, int _8t{4C
.,-t}5(VSq
currentPage, int totalRecords){ p-MQI }
everyPage = getEveryPage(everyPage); 3xbA]u;gp
currentPage = getCurrentPage(currentPage); )4 "G1R`3
int beginIndex = getBeginIndex(everyPage, D{\hPv
H2[S]`?
currentPage); h2K1|PUKl[
int totalPage = getTotalPage(everyPage, gy,B+~p
qJUu9[3'm
totalRecords); (7&[!PS
boolean hasNextPage = hasNextPage(currentPage, SkVW8n*s
?;!l-Dy
totalPage); -k")#1
boolean hasPrePage = hasPrePage(currentPage); cl)%qIXj}H
,}F{V>dhn
returnnew Page(hasPrePage, hasNextPage, enE8T3
everyPage, totalPage, /id(atiF^
currentPage, 6imDA]5N&
]#KZ
W)M
beginIndex); Ez+.tbEA,
} XoL9:s(m~
;}WdxWw4
privatestaticint getEveryPage(int everyPage){ V] <J^m8
return everyPage == 0 ? 10 : everyPage; @<r;>G
} L:j;;9Sp{
E*i <P
privatestaticint getCurrentPage(int currentPage){ ^DM^HSm
return currentPage == 0 ? 1 : currentPage; PG+ICg
} gtqgf<mS
ig)rK<@*[
privatestaticint getBeginIndex(int everyPage, int -"#;U`.oh7
_.yBX\tf[
currentPage){ =X]$J@j
return(currentPage - 1) * everyPage; |?i-y3N
} pd/{yX M
q>?uB4>^
privatestaticint getTotalPage(int everyPage, int 7P|GKN~
zHeqV
totalRecords){ Z<;am
int totalPage = 0; _/ ]4:("
4F^(3RKZ|
if(totalRecords % everyPage == 0) +'x|VPY.PG
totalPage = totalRecords / everyPage; ZQZ>{K
else R=_
fk
totalPage = totalRecords / everyPage + 1 ; R 6ca;
*&^`Uk,[
return totalPage; $x)C_WZj?
} v=RQ"iv8
^ dM,K
p
privatestaticboolean hasPrePage(int currentPage){ zkA"2dh
return currentPage == 1 ? false : true; ;n?H/(6X8>
} |Rf4^vN
$&