Hibernate3 提供了DetachedCriteria,使得我们可以在Web层构造 fp;a5||5
WeVi]n
detachedCriteria,然后调用业务层Bean,进行动态条件查询,根 mH\@QdF
BS2?!;,8
据这一功能,我设计了通用的抽象Bean基类和分页类支持,代码来 N!c
gN
ChE_unw
自于Quake Wang的javaeye-core包的相应类,然后又做了很多修改 +tUQ
w}`3 d@
。 9XOyj5
{Hk/1KG>
分页支持类: %VJW@S>j/
c;!9 \1sr
java代码: _yVPpA[a
4f {+pf^R
c0[k T
package com.javaeye.common.util; 6Xa.0(h
^73=7PZ
import java.util.List; ~:Mm<*lL%
}N,>A-P
publicclass PaginationSupport { e{!vNJ0`
H(> M
publicfinalstaticint PAGESIZE = 30; Zi4d]
=DMbz`t
privateint pageSize = PAGESIZE; U
~1SF
UvBnf+,
privateList items; JXm?2/
XeU<^ [
privateint totalCount; 8R4qU!M
tlGWl0V?7Q
privateint[] indexes = newint[0]; w~N-W8xNR
H[nz]s
privateint startIndex = 0; 7zGMkl
a5V=!OoMk
public PaginationSupport(List items, int o5 WW{)Q
7#pZa.B)k
totalCount){ }4h0bI
setPageSize(PAGESIZE); j@ v-|
setTotalCount(totalCount);
TQ' e
setItems(items); p;`N\.ld
setStartIndex(0); KB+]eI-h
} o](.368+4
m[8
@Unt
public PaginationSupport(List items, int `%y5\!X
SRf5W'4y
totalCount, int startIndex){ :hP58 }Q$
setPageSize(PAGESIZE); !01i%W'
setTotalCount(totalCount); h8.FX-0& =
setItems(items); [H^ X"D
setStartIndex(startIndex); _}ele+
} d?7BxYaa
V(..8}LlD
public PaginationSupport(List items, int (}~ucI<~
x6e +7"#~
totalCount, int pageSize, int startIndex){ {^m5#f 0"
setPageSize(pageSize); P(;Mb{
setTotalCount(totalCount); )U5u" ]9~
setItems(items); v{koKQ'Y()
setStartIndex(startIndex); MaErx\
} WG%2<Q^
,q</@}.\wN
publicList getItems(){ n7DLJ`ho{
return items; 2AK}D%jfc
} 6x4_b
voh^|(:(TH
publicvoid setItems(List items){ $1e pf
this.items = items; u[EK#%
} j^I!6j=ZX
+-ewE-:|L
publicint getPageSize(){ xwOE+
return pageSize; 0b++17aV
} 5hz_P+Q
@p]UvqtB@
publicvoid setPageSize(int pageSize){ 8\_*1h40s
this.pageSize = pageSize; ^ItAW$T]F
} hr~.Lj5^W
+WLD
publicint getTotalCount(){ $5L(gn[
return totalCount; NCDxcz;Gb
} ^c'f<<z|7r
$W, zO|-
publicvoid setTotalCount(int totalCount){ veO?k.u(
if(totalCount > 0){ Z =
ik{/
this.totalCount = totalCount; f4
O]`U
int count = totalCount / ]]y[t|6
PbN3;c3
pageSize; !NA`g7'
if(totalCount % pageSize > 0) 6t$N78U
count++; uO"8aD`W
indexes = newint[count]; 5!h<b3u>]
for(int i = 0; i < count; i++){ NWnWk
indexes = pageSize * U8[Qw}T P
)_Iz>)
i; {aIZFe}B
} 3'^S3W%
}else{ R@$+t:}
this.totalCount = 0; k=|K|
} r=\P!`{5
} `oXg<tivU
BA*&N>a
publicint[] getIndexes(){ ;qb Dbg
return indexes; y/\ZAtnLo
} u\3ZIb
pN+I]NgQ
publicvoid setIndexes(int[] indexes){ >~wu3q
this.indexes = indexes; -(
Kh.h
} KBj@V6Q
~'{VaYk]v
publicint getStartIndex(){ SwJHgZ&
return startIndex; r\RFDj
} hXTYTbTX
Om6Mmoqh
publicvoid setStartIndex(int startIndex){ niAZ$w
if(totalCount <= 0) WKOI\
this.startIndex = 0; #G~wE*VR$
elseif(startIndex >= totalCount) RNe9h lr
this.startIndex = indexes Gym#b{#":
Ys%'#f
[indexes.length - 1]; t%HI1eO7h
elseif(startIndex < 0) z L8J`W
this.startIndex = 0; h[y*CzG
else{ !mae^A1
this.startIndex = indexes B,MQ.|s[
q|Fjm]AF
[startIndex / pageSize]; C (U
} `GS cRhbh
} q#m!/wod
:mn(0
R~
publicint getNextIndex(){ "u5KbJW
int nextIndex = getStartIndex() + PY\W
jJ<;2e~OW
pageSize; (gDQ\t@3-
if(nextIndex >= totalCount) ;t~*F#p(!
return getStartIndex(); lJlhl7
else $':JI#
return nextIndex; sX!3_'-
} Wt"ww~h`(
}pKv.
publicint getPreviousIndex(){ Q!`)e @r
int previousIndex = getStartIndex() - XJ O[[G`
nfa_8
pageSize; '(T mV#3
if(previousIndex < 0) ?N`qLGRm
return0; ",QYDFFeF
else qL,ka
return previousIndex; X'xUwT|_+
} P*7S3Td
M$F{N
} Enu!u~1]F
e) ]RA?bF
PY2[S[
}\DAg'e)
抽象业务类 , !r@9T
java代码: :q(D(mK
9QC< E|
9@Q&B+!
/** O%52V|m}{
* Created on 2005-7-12 27Cz1[oX
*/ D$QGL I9(
package com.javaeye.common.business; 3Fgz)*Gu]
)U]:9)
import java.io.Serializable; %n4@[fG%K
import java.util.List; +;YE)~R?
vUqe.?5
import org.hibernate.Criteria; J}:&eS
import org.hibernate.HibernateException; ed=n``P~}
import org.hibernate.Session; IeH^Wm&^
import org.hibernate.criterion.DetachedCriteria; dV)Y,Yx0${
import org.hibernate.criterion.Projections; X=JFWzC
import WFRsSp2
~m!#FTc*
org.springframework.orm.hibernate3.HibernateCallback; :MK:TJV
import R9Ldl97'
#t){ 4J
org.springframework.orm.hibernate3.support.HibernateDaoS k]t,q$Vd
xna7kA
upport; 'y< t/qo
b By'v/
import com.javaeye.common.util.PaginationSupport; Ywmyr[Uh'
akMJ4EF/
public abstract class AbstractManager extends
ccRlql(
)4@M`8
HibernateDaoSupport { J`4Z<b53
:-(U%`a[
privateboolean cacheQueries = false; s%5Uj}
j,\tejl1
privateString queryCacheRegion; cT\Ov
P*_
K!9y+%01
publicvoid setCacheQueries(boolean DE'Xq6#PK
3'.!
+#
cacheQueries){ HJc<Gwm
this.cacheQueries = cacheQueries; Sw yaYK
} K*TnUQ
F
~*zC`>Y
publicvoid setQueryCacheRegion(String p@vpd
" 98/HzR
queryCacheRegion){ u$ap H{
this.queryCacheRegion = %B[YtWqm`/
Tc9&mKVE%(
queryCacheRegion; ,?Ok[G!cm
} TFNUv<>X
d:A\<F
publicvoid save(finalObject entity){ +d.u##$
getHibernateTemplate().save(entity); _L8Mpx*E
} hJecCOA)'
>9 q]>fJ
publicvoid persist(finalObject entity){ G!nl'5|y
getHibernateTemplate().save(entity); mp!YNI
} <}<#W/
qi(&8in
publicvoid update(finalObject entity){ ~u};XhZ
getHibernateTemplate().update(entity); sq6>DuBZz
} T@B"BoKU
7We?P,A\;
publicvoid delete(finalObject entity){ f$Gr`d
getHibernateTemplate().delete(entity); yZ?xt'tn
} JtSuD>H`"
@P*ylB}?Q
publicObject load(finalClass entity, ~o:rM/!Ba
=s`XZkh
finalSerializable id){ ,?C|.5
return getHibernateTemplate().load &/ \O2Aw8
h1n*WQ-
(entity, id); c$@`P
} d,zp`S
Q1aHIc
publicObject get(finalClass entity, 976E3u"Vt
KX0<j
finalSerializable id){ mk#>Dpy?
return getHibernateTemplate().get r3n=<l!Jr
UAnB=L,.\
(entity, id);
fn4=
} 5T~3$kuO
s;vWR^Ll
publicList findAll(finalClass entity){ 98X!uh'
return getHibernateTemplate().find("from ?lu_}t]
d-9uv|SJ
" + entity.getName()); kEp.0wL'
} X(4s;i
<]Ij(+J;
publicList findByNamedQuery(finalString FgXu1-
2 9&sydu
namedQuery){ "2*G$\
return getHibernateTemplate qXXYF>Z-
AQE
eIFH
().findByNamedQuery(namedQuery); Hlz'a1\:O]
} pw0Px
|Dl*w/n
publicList findByNamedQuery(finalString query, }@3Ud'
Y
w%>aR_G
finalObject parameter){ b7?U8/#'
return getHibernateTemplate MDMtOfe|
}v_p gatC
().findByNamedQuery(query, parameter); szf"|k!
} Zkf 3t>[
*54>iO-
c
publicList findByNamedQuery(finalString query, JoZqLy!@
&{X{36
finalObject[] parameters){ b=6MFPbg
return getHibernateTemplate SZCF3m&pz
LEYWH%y
().findByNamedQuery(query, parameters); %1Vu=zCAW
} v[0DE*p
E"Ya-8d=
publicList find(finalString query){ kWzuz#
return getHibernateTemplate().find jlYD~)
FZ[@])B
(query); X=rc3~}f
} '"!z$i~G=
`,F&y{A
publicList find(finalString query, finalObject u5xU)l3
vGx?m@
parameter){ 9oZ}
h&
return getHibernateTemplate().find BSx j~pun
1Z^`l6|2
(query, parameter); 4M;sD;3
} tQNk=}VR7r
i /O1vU#
public PaginationSupport findPageByCriteria [W^6u7~
o0,UXBx
(final DetachedCriteria detachedCriteria){ -ET*M<
return findPageByCriteria $=e&q
u=p ;A1oy
(detachedCriteria, PaginationSupport.PAGESIZE, 0); W?*Xy6",JF
} aukk|/3Ih
[@,OG-"&
public PaginationSupport findPageByCriteria />dB%*
tc+GR?-7W
(final DetachedCriteria detachedCriteria, finalint t_[M&
tIn7(C
startIndex){ [;>zqNy
return findPageByCriteria r;&]?9)W0
-mev%lV
(detachedCriteria, PaginationSupport.PAGESIZE, c!'A)JD@
Ze[g0"
startIndex); #rn4$
} (lyt"Ty
k| _$R?
public PaginationSupport findPageByCriteria '1>g=Ic0
=oL8d6nI
(final DetachedCriteria detachedCriteria, finalint 9;E%U2T7
5}.,"Fbr
pageSize, m.\ >95!
finalint startIndex){ )LXoey!aZ
return(PaginationSupport) v`[Tl
%v?jG(o
getHibernateTemplate().execute(new HibernateCallback(){ AijPN
publicObject doInHibernate "E@NZ*"u
[
4?cM\_u@
(Session session)throws HibernateException { 4*p_s8> >
Criteria criteria = 9%p7B ~}E
!$:0E
y(S
detachedCriteria.getExecutableCriteria(session); M iP[UCh
int totalCount = d1srV`
otmIu` h
((Integer) criteria.setProjection(Projections.rowCount b
xk'a,!S
|'V<>v.v
()).uniqueResult()).intValue(); IqvqvHxLX
criteria.setProjection LVR;&Z>j
B-y0;0
(null); E%wV
List items = [?|l X$<
lKh2LY=j
criteria.setFirstResult(startIndex).setMaxResults VTy,43<
P.[6s$J
(pageSize).list(); ?V&Ld$db
PaginationSupport ps = Bo](n*i
p`E|SNt/W
new PaginationSupport(items, totalCount, pageSize, f"5lOzj`C
<r_P?
lZW
startIndex); >5Q^9 9V
return ps; [OFTP#}c
} Pi&fwGL
}, true); B|]t\(~$[
} %fn'iKCB
;Zx K3/(7
public List findAllByCriteria(final *([0"
boC>N
DetachedCriteria detachedCriteria){ h3UZ|B0=
return(List) getHibernateTemplate Gx(K N57D
wf~5lpI[
().execute(new HibernateCallback(){ :,h=2a_ 8
publicObject doInHibernate {<-
ouD
Ak\D6eHcB
(Session session)throws HibernateException { <'>d0:>N
Criteria criteria = +BtLyQ
yBYuDfeZ
detachedCriteria.getExecutableCriteria(session); )o
" SB1
return criteria.list(); N27K
} {a+Fx}W
}, true); )*^OPVt
} >j(I[_g
Q>SPV8s
public int getCountByCriteria(final 3<KZ.hr
:)A.E}G
DetachedCriteria detachedCriteria){ VV0EgfJ
Integer count = (Integer) %9~kA5Qj
KV^:sxU
getHibernateTemplate().execute(new HibernateCallback(){ q_9N+-?{7
publicObject doInHibernate nK?k<
DU*g~{8T$
(Session session)throws HibernateException { .v
#0cQX+.
Criteria criteria = 8T>3@kF
y]QQvCJr3d
detachedCriteria.getExecutableCriteria(session); |*]X\UE
return zCj*:n
=#POMK".6
criteria.setProjection(Projections.rowCount d!}jdt5%
xVHQ[I%
()).uniqueResult(); fJF8/IQ4
} V\k5h
}, true); 7)8rc(58
return count.intValue(); np'M4^E;
} w{YtTZp3
} JL]k:i^`A
7N} \1Di5
oSu|Yn
y7;XOPm
AXNszS%4
a!^-~pH:
用户在web层构造查询条件detachedCriteria,和可选的 <M=W)2D7
zal3j^
startIndex,调用业务bean的相应findByCriteria方法,返回一个 DMK"Q#Vw
Fu1|b2B-x
PaginationSupport的实例ps。 XqE55Jclp
TeGLAt
ps.getItems()得到已分页好的结果集 eBSn1n
ps.getIndexes()得到分页索引的数组 3-9J"d!
ps.getTotalCount()得到总结果数 |$.sB|_
N
ps.getStartIndex()当前分页索引 ZaNyNxbp>z
ps.getNextIndex()下一页索引 5Re`D|8
ps.getPreviousIndex()上一页索引 9|G=KN)P:
"b1R5(Ar
K;ry4/Vap
^;bGP.!p
35@Ibe~
e%@[d<Ta\
4s1kZ`e
连续看了两篇robbin有关DetachedCriteria的介绍,感觉真的不错 P5
<85t
wNf*/?N
,尤其是上面的示例代码,让我着实觉得该对我原来的分页查询做 g`~lIt[=
3*2&Fw!B
一下代码重构了。 yN WbI0a
W"}*Q-8W
我把原本我的做法也提供出来供大家讨论吧: 6M<mOhp@}n
N8L)KgM5#7
首先,为了实现分页查询,我封装了一个Page类: V"2AN3~&
java代码: H,4,~lv|
g*w-"%"O
.2(@jx,[
/*Created on 2005-4-14*/ >ihe|WN
package org.flyware.util.page; ZZFI\o
HZr/0I?
/** cVP49r}}v
* @author Joa |$|n V^y
* *2m&?,nJ
*/ t#D\*:Xi
publicclass Page { 7z P
/xrq'|r?C
/** imply if the page has previous page */ /J9T=N
privateboolean hasPrePage; "` ?Wu
rfZj8R&
/** imply if the page has next page */ (?&_6B.*
privateboolean hasNextPage; u7y7
C)3$";$5)
/** the number of every page */ h}B# 'e
privateint everyPage; 6 peM4X
woH3?zR
/** the total page number */ |z<wPJ,;2
privateint totalPage; ]BS{,sI
We+FP9d %
/** the number of current page */ ;u-< {2P
privateint currentPage; kAQ\t?`x
W%jX-
/** the begin index of the records by the current <hF~L k ,
@9kk
f{?
query */ 8Jy1=R*S
privateint beginIndex; y3o4%K8
M3Z Jt' |
?=@Q12R)X
/** The default constructor */ H R!>g
public Page(){ j>Bk; f|
Mb/6>
} PJ11LE
2DBFXhP
/** construct the page by everyPage ? Ge*~d
* @param everyPage m+gG &`&u
* */ %Pvb>U(Xs
public Page(int everyPage){ !\k#{
1[!
this.everyPage = everyPage; y88}f&z#5
} {ZIFj.2
Mp@(/
/** The whole constructor */ ,E8>:-boL
public Page(boolean hasPrePage, boolean hasNextPage, Y"\T*lKa
3<'Q`H >
sFz4^Kn
int everyPage, int totalPage, N n-6/]d#
int currentPage, int beginIndex){ mBgx17K/-_
this.hasPrePage = hasPrePage; Y X{
this.hasNextPage = hasNextPage; [Oy2&C
this.everyPage = everyPage; AFhG{G'W
this.totalPage = totalPage; `
Ehgn?6'
this.currentPage = currentPage; }Yl8Q>t
this.beginIndex = beginIndex; "s6_lhu=E7
} bg3jo1J
7R`ZTfD
/** 9kg>)ty@
* @return ^fiRRFr[
* Returns the beginIndex. md
+`#-D\O
*/ czsoD)N
publicint getBeginIndex(){ SFPIr0 u
return beginIndex; ;@-5lCvC(+
}
! +VN
9DAwC:<r
/** FEi,^V
* @param beginIndex Ly/~N/<\
* The beginIndex to set. _j<M}
*/ iuk8c.TAR
publicvoid setBeginIndex(int beginIndex){ mS;Q8Crh
this.beginIndex = beginIndex; r_<i*l.
} \C\y'H5
A)a+LW'=u
/** 4Jy,IKPp
* @return <W|{)U?p
* Returns the currentPage. kX .1#%Ex
*/ b6$A@b
publicint getCurrentPage(){ 9oN'.H^
return currentPage; )PNH| h
} 8uD%]k=#!
<^c0bY1
/** nk,Mo5iqV
* @param currentPage T`<k4ur
* The currentPage to set. O*Pe[T5x'
*/ R/FV'qy]
publicvoid setCurrentPage(int currentPage){ Ytnr$*5.
this.currentPage = currentPage; #K*q(ei,7h
} ]x{ H
_^sSI<&m
/** ^
J@i7FOb
* @return !Kqj&y5
* Returns the everyPage. E1Aa2
*/ _~&vs<
publicint getEveryPage(){ en6AAr:U}
return everyPage; eOO*gM=
} MP&4}De
U~@B%Msb
L
/** Fm~}A4
* @param everyPage mNB ]e5;N
* The everyPage to set. %z_b/yG
*/ &`y_R'
publicvoid setEveryPage(int everyPage){ Vk=<,<BB
this.everyPage = everyPage; 3>3ZfFC
} XzFqQ-H
@?AE75E{
/** *jSc&{s~
* @return _^$b$4)
* Returns the hasNextPage. %ycT}Lu
*/ s"!}=kX
publicboolean getHasNextPage(){ (:k`wh&
return hasNextPage; 4tu>~ vOE
} fBh|:2u
FOyfk$
/** BrmFwXLP"
* @param hasNextPage xyCcd=
* The hasNextPage to set. WZ-{K"56
*/ Ybiz]1d
publicvoid setHasNextPage(boolean hasNextPage){ A^7Zy79
this.hasNextPage = hasNextPage; Ev ,8?
} Ekp
0.c8:
D\~$6#B>>
/** o6%f%:&
* @return ZlXs7
&_
* Returns the hasPrePage. {%}6d~Bg
*/ ~OfKn1D
publicboolean getHasPrePage(){ wWswuhq<
return hasPrePage; SvrV5X
} KAEpFobYo
U .jMK{
/** I4ct``Di
* @param hasPrePage :dc
J6
* The hasPrePage to set. P?ol]MwaB
*/ z1A-EeT
publicvoid setHasPrePage(boolean hasPrePage){ !.N=Y;@lY
this.hasPrePage = hasPrePage; ~&|i'f[
} c=E.-
Cagq0-:(p
/** FJ.
:*K[
* @return Returns the totalPage. jH/%Z5iu
* LM`#S/h
*/
0$uS)J\;K
publicint getTotalPage(){ ur5n{0#
return totalPage; +6E<+-N
} o?8j*]
.v8=zi:7Y
/** ee\zU~
* @param totalPage \wd`6
* The totalPage to set. `N,Jiw;bw
*/ j0M;2 3@[
publicvoid setTotalPage(int totalPage){ YR#1[fe*_
this.totalPage = totalPage; 0M.[) @
} ZS;kCdL
ZXkAw sr
} AG=1TZI"
>qZRIDE5$
mJqP#Unik
y[eNM6p
Y^f|}YO%y
上面的这个Page类对象只是一个完整的Page描述,接下来我写了一 K|!)<6ZsG7
-v&srd^
个PageUtil,负责对Page对象进行构造: V!!'S
h
java代码: _Y~?. hs^
v:b%G?o
|9JYg7<
/*Created on 2005-4-14*/ LRgk9*@,
package org.flyware.util.page; 94/}@<d-=
o4795r,jz
import org.apache.commons.logging.Log; Yq.@7cJ
import org.apache.commons.logging.LogFactory; 69L&H!<i:
]kvE+m&p}^
/** '93&?
* @author Joa c" HCc]
* fTcRqov
*/ ~=Sr0+vV
publicclass PageUtil { ;T(^riAEl
b`=rd 4cpU
privatestaticfinal Log logger = LogFactory.getLog ,+{ 43;a
N/p_6GYMa
(PageUtil.class); v<**GW]neD
xbIA97g-O,
/** Y6Q6--P
* Use the origin page to create a new page 0eIR)#j*
* @param page CQ ?|=cN
* @param totalRecords eIl&=gZ6>
* @return BC+qeocg
*/ ~A( Pa-
publicstatic Page createPage(Page page, int ^a
r9$$~/!
u[@*}|uXM
totalRecords){ % *hBrjbj
return createPage(page.getEveryPage(), q3t@)+l>*
re2%e-F"
page.getCurrentPage(), totalRecords); a!.8^:B&
} F.9|$g*ip
kM@,^`&
/** P n DZi
* the basic page utils not including exception FUqiP(A
HC$cK+,ZU}
handler C2T,1 =
* @param everyPage )c_ll;%
* @param currentPage T9 1Iz+j
* @param totalRecords J KGZ0yn
* @return page 9:>vl0
*/ yo=d"*E4^
publicstatic Page createPage(int everyPage, int mbK$Wp#
2
r)c?
currentPage, int totalRecords){ 3]Mx,u
everyPage = getEveryPage(everyPage); zjS<e
XLs[
currentPage = getCurrentPage(currentPage); EWi@1PAZK
int beginIndex = getBeginIndex(everyPage, :yeTzIz]
?T&D@Ohsx
currentPage); shRvwE[
int totalPage = getTotalPage(everyPage, r}w 9?s^rB
LGkKR{ep(
totalRecords); wO9<An
boolean hasNextPage = hasNextPage(currentPage, Z'~FZRF
t<=L&:<N
totalPage); I&9B^fF6
boolean hasPrePage = hasPrePage(currentPage); 1['A1,
sQ$FtKm6
returnnew Page(hasPrePage, hasNextPage, :1I,:L
everyPage, totalPage, PC5FfX
currentPage, P:o<kRj1
E7,\s
beginIndex); lPQH_+)Z"
} *Bj G3Jc5
B^Q#@[T
privatestaticint getEveryPage(int everyPage){ 6lGL.m'Ra
return everyPage == 0 ? 10 : everyPage; (`N/1}vk
}
~a}pYLxl
<f%9w]
privatestaticint getCurrentPage(int currentPage){ zq#o8))4X
return currentPage == 0 ? 1 : currentPage; 8~bPoWP
} 3ml|`S
$n ) w4p_
privatestaticint getBeginIndex(int everyPage, int utXcfKdt
e:]$UAzp
currentPage){ ;-F#a+2]!
return(currentPage - 1) * everyPage; -MZ Eli g
} pJIH_H
"#()4.9
privatestaticint getTotalPage(int everyPage, int ^/,s$dj
FWj~bn
totalRecords){ !}%giF$-
int totalPage = 0; [
kknY+n1
{+ m)*3~w
if(totalRecords % everyPage == 0) K:0RP?L
totalPage = totalRecords / everyPage; n.)-aRu[
else #rC% \
totalPage = totalRecords / everyPage + 1 ; ?{n#j,v!
sC$X7h(Q+
return totalPage; N=kACEo
} ^s-3U
kF5}S8B
privatestaticboolean hasPrePage(int currentPage){ 5"sF#Y&
return currentPage == 1 ? false : true; <