jdbc调用通用存储过程完成分页

 

分页是我们做WEB系统必备的技术了,但是分页的方式却多种多样,有客户端分页,服务器端分页,以及它们的折中等等。这里我们简单的说一下:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

客户端分页:由WEB服务器的组件一次性从数据库服务器的表中取出全部数据,再存储在自身的内存中。好处是以后需要某页数据时不用再重新查找数据库,直接从自身的内存中取到,大大节约时间开销;坏处是浪费了内存空间,当数据海量时明显不合适。

服务器端分页:每当用户需要浏览某一页的数据时,就由WEB服务器的组件建立和数据库服务器的连接并取出相应数据。好处是本着节约精神,用多少就取多少;坏处是每次分页都要访问数据库,时间开销大,性能下降。

二者的折中:既然没有完美,那我们只有折中了。所谓折中当然就是在反应时间和内存空间上取得平衡,典型的例子就是baidugoogle搜索的分页了。我们可以每次取10页或者20页的数据存储在WEB服务器的内存中,这样当某页的数据存在于内存就直接从中取出,不存在再去访问数据库。既不占用大量内存空间,也不用每次翻页都要花时间去访问数据库。

 

       我们在这里给大家介绍的主要是服务器端分页,并且用存储过程来实现。以sqlserver2000为例,我们先来看一下一个查找book(主键为b_id)进行分页的简单存储过程:

CREATE PROC findAllBookDemo

@pageIndex int,

@pageSize int

as

begin

declare @SQL varchar(1000)

set @SQL='select top '

       +cast(@pageSize as varchar)

       +' * from book where b_id not in (select top '

       +cast((@pageIndex-1)*@pageSize as varchar)

       +' b_id from book)'

exec (@SQL)

end

       sqlserver 2000的查询分析器中运行exec findAllBookDemo 1,3就可以查询到第1页的最多3条记录。

       但这个存储过程太简单了,它只能查找book表,而且不能排序和过滤,下面我们来看一个更通用的分页存储过程:

/*

经测试,在 14483461 条记录中查询第 100000 页,每页 10 条记录按升序和降序第一次时间均为 0.47 秒,第二次时间均为 0.43 秒,测试语法如下:

exec GetRecordByPage tableName,id,10,100000

tableName为表名, id为主键

*/

 

/*

函数名称: GetRecordByPage

函数功能: 获取指定页的数据

参数说明: @tblName 包含数据的表名

@fldName 关键字段名

@PageSize 每页记录数

@PageIndex 要获取的页码

@OrderType 排序类型, 0 - 升序, 1 - 降序

@strWhere 查询条件 (注意: 不要加 where)

*/

CREATE PROCEDURE GetRecordByPage

@tblName varchar(255), -- 表名

@fldName varchar(255), -- 字段名

@PageSize int = 10, -- 页尺寸

@PageIndex int = 1, -- 页码

@OrderType bit = 0, -- 设置排序类型, 0 值则降序

@strWhere varchar(2000) = '' -- 查询条件 (注意: 不要加 where)

AS

declare @strSQL varchar(6000) -- 主语句

declare @strTmp varchar(1000) -- 临时变量

declare @strOrder varchar(500) -- 排序类型

if @OrderType != 0

begin

set @strTmp = '<(select min'

set @strOrder = ' order by [' + @fldName + '] desc'

end

else

begin

set @strTmp = '>(select max'

set @strOrder = ' order by [' + @fldName +'] asc'

end

set @strSQL = 'select top ' + str(@PageSize) + ' * from ['

+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['

+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['

+ @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'

+ @strOrder

if @strWhere != ''

set @strSQL = 'select top ' + str(@PageSize) + ' * from ['

+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['

+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['

+ @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '

+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder

if @PageIndex = 1

begin

set @strTmp = ''

if @strWhere != ''

set @strTmp = ' where (' + @strWhere + ')'

set @strSQL = 'select top ' + str(@PageSize) + ' * from ['

+ @tblName + ']' + @strTmp + ' ' + @strOrder

end

exec (@strSQL)

GO

       sqlserver 2000的查询分析器中运行exec GetRecordByPage book,b_id,3,1,1,'b_id<>3'就可以查询到book表中第1页的最多3条的记录。它以b_id为主键,过滤条件为b_id<>3,并且按照降序排列。那这样是不是大功告成了呢?当然没有,我们还要能够用JDBC操作这个存储过程来获得查询的记录呢!核心测试代码如下:

              try {

                     CallableStatement cs = con.prepareCall("{call GetRecordByPage(?,?,?,?,?,?)}");

                     cs.setString(1, "book");

                     cs.setString(2, "b_id");

                     cs.setInt(3, 3);

                     cs.setInt(4, 1);

                     cs.setInt(5, 1);

                     cs.setString(6, "b_id<>3");

                     ResultSet rs = cs.executeQuery();

                     while(rs.next()){

                            System.out.println(rs.getInt(1)+" "+rs.getString(2));

                     }

              } catch (SQLException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

              }

       }

}

       呵呵,这样子你就知道在java WEB应用中如何根据不同状况来使用不同的分页策略,更重要的是怎么样写一个高效而通用的存储过程来完成分页功能了。当然最终少不了获取存储过程查询出来的数据,而这一点,对于JDBC而言,就和操作普通SQL语句一样简单。好啦,时间紧迫,就写到这里,祝各位学习愉快!

原文地址:https://www.cnblogs.com/CharmingDang/p/9663797.html