在看JPetStore的代码时,发现它的分页处理主要是通过返回PaginatedList对象来完成的。如:在CatalogService类中
public
PaginatedList getProductListByCategory(String categoryId)
{
return
productDao.getProductListByCategory(categoryId);
}
分页是操作数据库型系统常遇到的问题。分页实现方法很多,但效率的差异就很大了。iBatis是通过什么方式来实现这个分页的了。查看它的实现部分:
返回的PaginatedList实际上是个接口,实现这个接口的是PaginatedDataList类的对象,查看PaginatedDataList类发现,每次翻页的时候最后都会调用下面这段函数
private
List getList(
int
idx,
int
localPageSize)
throws
SQLException
{
return
sqlMapExecutor.queryForList(statementName, parameterObject, (idx)
*
pageSize, localPageSize);
}
由于
public
interface
SqlMapClient
extends
SqlMapExecutor, SqlMapTransactionManager
{……}
所以实际的调用次序如下:
SqlMapClientImpl.queryForPaginatedList
->
SqlMapSessionImpl.queryForPaginatedList
->
SqlMapExecutorDelegate.queryForPaginatedList
->
GeneralStatement.executeQueryForList
->
GeneralStatment.executeQueryWithCallback
->
GeneralStatment.executeQueryWithCallback
->
SqlExecutor.executeQuery
->
SqlExecutor.handleMultipleResults()
->
SqlExecutor.executeQuery
->
handleResults
分页处理的函数如下
private
void
handleResults(RequestScope request, ResultSet rs,
int
skipResults,
int
maxResults, RowHandlerCallback callback)
throws
SQLException
{
try
{
request.setResultSet(rs);
ResultMap resultMap
=
request.getResultMap();
if
(resultMap
!=
null
)
{
//
Skip Results
if
(rs.getType()
!=
ResultSet.TYPE_FORWARD_ONLY)
{
if
(skipResults
>
0
)
{
rs.absolute(skipResults);
}
}
else
{
for
(
int
i
=
0
; i
<
skipResults; i
++
)
{
if
(
!
rs.next())
{
return
;
}
}
}
//
Get Results
int
resultsFetched
=
0
;
while
((maxResults
==
SqlExecutor.NO_MAXIMUM_RESULTS
||
resultsFetched
<
maxResults)
&&
rs.next())
{
Object[] columnValues
=
resultMap.resolveSubMap(request, rs).getResults(request, rs);
callback.handleResultObject(request, columnValues, rs);
resultsFetched
++
;
}
}
}
finally
{
request.setResultSet(
null
);
}
}
由
此可见,iBatis的分页主要依赖于jdbcdriver的如何实现以及是否支持rs.absolute(skipResults)。它并不是一个好的
分页方式。它先要取出所有的符合条件的记录存入ResultSet对象,然后用absolute方法进行定位,来实现分页。当记录数较大(比如十万条)
时,整体的查询速度将会变得很慢。
所以分页还是要考虑采用直接操作sql语句来完成。当然小批量的可以采用iBatis的分页模式。一般分页的sql语句与数据库的具体实现有关
mysql:
select
*
from
A limit startRow,endRow
oracle:
select
b.
*
from
(
select
a.
*
,rownum
as
linenum
from
(
select
*
from
A) a
where
rownum
<=
endRow) b
where
linenum
>=
startRow
Hibernate的Oracle分页采用的就是是拼凑RowNum的Sql语句来完成的。参考代码如下:
public
String createOraclePagingSql(String sql,
int
pageIndex,
int
pageSize)
{
int
m
=
pageIndex
*
pageSize;
int
n
=
m
+
pageSize;
return
"
select * from ( select row_.*, rownum rownum_ from (
"
+
sql
+
"
) row_ where rownum <=
"
+
n
+
"
) where rownum_ >
"
+
m;
}
综上,小批量(<2w)可以采用ibatis自带的分页类,大批量的还是直接操纵sql,当然也可以将这些sql自己进行封装,或在包中封装都可以。包封装的示例代码如下:
一个封装了分页功能的Oracle Package
create
or
replace
package body FMW_FY_HELPER
is
PROCEDURE
GET_DATA(pi_sql
in
varchar
,pi_whichpage
in
integer
,pi_rownum
in
integer
,
po_cur_data out cur_DATA,po_allrownum out
integer
,pio_succeed
in
out
integer
)
as
v_cur_data cur_DATA;
v_cur_temp cur_TEMP;
v_temp
integer
;
v_sql
varchar
(
5000
);
v_temp1
integer
;
v_temp2
integer
;
begin
pio_succeed :
=
1
;
v_sql :
=
'
select count(
''
a
''
) from (
'
||
pi_sql
||
'
)
'
;
execute
immediate v_sql
into
v_temp;
po_allrownum:
=
ceil(v_temp
/
pi_rownum);
v_sql :
=
''
;
v_temp :
=
pi_whichpage
*
pi_rownum
+
1
;
v_temp1:
=
(pi_whichpage
-
1
)
*
pi_rownum
+
1
;
v_temp2:
=
pi_whichpage
*
pi_rownum;
v_sql:
=
'
select * from (select rownum as rn,t.* from (
'
||
pi_sql
||
'
) t where rownum<
'
||
to_char(v_temp)
||
'
) where rn between
'
||
to_char(v_temp1)
||
'
and
'
||
to_char(v_temp2);
open
v_cur_data
for
v_sql;
if
v_cur_data
%
notfound
then
pio_succeed:
=-
1
;
return
;
end
if
;
po_cur_DATA :
=
v_cur_data;
end
;
分享到:
相关推荐
NULL 博文链接:https://tianke645.iteye.com/blog/876116
ibatis 分页功能,使用了标签page.tld。本代码不能单独运行,技术能力欠缺或者代码阅读能力不是很好的朋友,请勿下载。
ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件 ibatis_likehbm高效分页组件 ibatis_likehbm...
公司的大部分项目都开始使用IBatis作为O/R Mapping了,但是在使用的过程中也发现了很多不方便和存在争议的地方,其中一个不方便的地方就是分页,目前的处理方式都是在sqlMap中写针对特定数据库的物理分页Sql语句,对于...
NULL 博文链接:https://joint.iteye.com/blog/557830
ibatis实现分页技术,其中的分页都已经封装好了,大家需要的话可以下载下来看下
ibatis 物理分页jar ,与官方ibatis不冲突,可直接使用。
Ibatis .net 分页 查询, 可以参考下, Ibatis .net 分页 查询
iBatis分页源代码解析.chm,ibatis介绍等
Xwork+iBatis的分页,简单好用,jsp页面无需写复杂代码,只是把分页的bar从request中取出来就好,一看就懂,简单好用。
一直以来ibatis的分页都是通过滚动ResultSet实现的,应该算是逻辑分页吧。逻辑分页虽然能很干净地独立于特定数据库,但效率在多数情况下不及特定数据库支持的物理分页,而hibernate的分页则是直接组装sql,充分利用...
底层 到 页面展示 , dao层 service层 action层 到tld 到jsp都是、已经写好 你只要调用就可以。非常好用的jsp分页标签(如果不明白的地方,可以私聊我)
NULL 博文链接:https://sarin.iteye.com/blog/1026061
Ibatis SQLServerDialect 2008 分页 可实现SQLServerDialect 分页 支持ibatis3
Ibatis 2.3.4 数据库无关分页 有示例,可以运行 网上找的很不错
NULL 博文链接:https://jsufly.iteye.com/blog/508249
spring+ibatis+oracle分页缓存源码
博文链接:https://qdj21.iteye.com/blog/233137
ibatis调用oracle存储过程分页
通过修改ibatis源码实现sql分页。由于ibatis默认分页是全部查出,然后再从中取出相应的数据实现分页,效率底。所以需要扩展