jsp+mysql分页技巧:巧用limit 进行分页查询

来源:互联网 发布:阿里云管理控制台首页 编辑:程序博客网 时间:2024/05/22 17:03

发现问题:

 

 

今天检查web程序,浏览“彩信xxxx日志”时,突然发现该web程序中不能浏览了,出错了,如下:
500 Servlet Exception

java.lang.OutOfMemoryError


Resin-3.0.6 (built Tue, 20 Jan 2004 09:46:57 PST)

查找原因:

怎么会呢?一直运行好好的程序,开始以为程序更新上传时弄错了,检查了多次没有发现代码问题,后来逐句调试,终于找到了原因:问题出在这里

sql="select * from MMS_Chat_MsgLog where 1=1 order by ID";

prepStmt=conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);

rs = prepStmt.executeQuery();

我这个页面是用jsp从库中查数据然后在前台分页显示,先返回ResultSet记录集,rs.last();rs.getRow();得到记录总数,然后根据查询页次和页面大小,使用rs.absolute(posion);语句设置记录游标的位置,把记录显示到页面。

起初数据库中记录并不多,返回rs没有问题,但是随着记录增多(查了一下有20多万条吧)这样再返回rs就出问题了,即使不出错返回速度也是很慢,因为select * from 要缓存所有记录。

       我把sql改了一下,="select * from MMS_Chat_MsgLog where 1=1 order by ID limit 10";再次执行,OK了,页面没有报错。确定了以上就是问题原因,就是返回记录集太多,机器不干了。从网上查询了一些关于jsp分页技术介绍,也是这么说的。

解决办法:

       如果按照网上一些例子修改起来非常麻烦,我不想对原来的代码进行大动手术。突然想到了,可以利用mysqlsql语法中limit来完成这个任务。Limit 有两个参数 (语法:limit 参数1,参数2)参数1是记录指针位置,参数2是返回记录数。呵呵,唯一要改得地方就是:得到记录总数的方法 原来的sql后加上limit语句就OK 了。

改造如下:

//分页显示(页次信息从用户确定页面获取)

int pageno=1;//页次-默认第一页

int pagesize=20;//页面显示记录数

int pagecount=1;//页数默认1

int rscount=0;//记录总数

String pagenoStr=request.getParameter("pageno")==null?"1":request.getParameter("pageno");

String pagesizeStr=request.getParameter("pagesize")==null?String.valueOf(pagesize):request.getParameter("pagesize");;

try{

       pageno=Integer.parseInt(pagenoStr);

       pagesize=Integer.parseInt(pagesizeStr);

}

catch(Exception e)

{

       pageno=1;

       pagesize=20;

       e.printStackTrace();

       out.println("<br>[mms_income.jsp] find error0:"+e.toString());

}

//查询用户信息

String sql="";  //说明:sql是根据条件动态产生的半句sql

       if(MsgFlag.equals("")){

              sql="from MMS_Chat_MsgLog where 1=1";

       }else{

              sql="from MMS_Chat_MsgLog where 1=1 and MsgFlag="+MsgFlag+"";

       }

       if(!UserMobile.equals("")){

              sql=sql+" and UserMobile='"+UserMobile+"'";

       }

       sql=sql+" order by ID";

 

 

String sqlTmp="select count(*) "+sql;   rs = stmt.executeQuery(sqlTmp);

rs.next();

int lastRow=rs.getInt(1);

rs.close();

//原来的方法注释掉了

//rs.last();

//int lastRow=rs.getRow();//获取最后一行的行号

 

 

这样轻松的到了记录数,下面就很简单了

//计算分页后的总页数

      pagecount = (lastRow%pagesize==0)?(lastRow/pagesize):(lastRow/pagesize+1);

      rscount=lastRow;

      if(pageno>=pagecount)pageno=pagecount;

      int curtRsCount=0;

      if(lastRow!=0)

         {

          int posion=(pageno-1)*pagesize+1;

//如果要显示第pageno页,那么游标应移到posion的位置

          sql="select * "+sql+" limit "+posion+","+pagesize; //嘿嘿,这句话是新改造的

          rs=stmt.executeQuery(sql);

      }

//下面就是显示记录的语句了。

while(rs.next())

{

//显示记录信息到页面

}

 

 

显示页次:

<script language=javascript>

function ChangePage(){

       document.Form1.pageno.value=Form2.pagenoTmp.value;

       Form1.submit();

}

</script>

<form method="POST" action="" id=Form2 name=Form2>

<!--页次信息--Begin-->

<b><%=pagecount%>页,共<%=rscount%>条,每页<%=pagesize%>条;目前显示第<%=pageno%>页。</b>

<br>

<%

int pagestart=1;

int pagestop=1;

 

 

pagestart=pageno-5<1?1:pageno-5;

pagestop=pageno+5>pagecount?pagecount:pageno+5;

 

 

for(int ix=pagestart;ix<=pagestop;ix++){%>

       <a href=?UserMobile=<%=UserMobile%>&MsgFlag=<%=MsgFlag%>&pageno=<%=ix%>><%if(ix==pageno){%><font color=red size=3><b><%=ix%></b></font><%}

              else{%><%=ix%><%}%></a>&nbsp;

<%}%>

<!--页次信息--End-->

       转到第<input type="text" name="pagenoTmp" size="7" value="<%=pageno%>"><input type="button" value="GO" name="B3" onclick="ChangePage()">

</form>

 

 

 

 

以上只是jsp+mysql 进行分页的应用,至于其他数据库(Oracle,SQLServer),如果用原始的分页方法中计算(返回记录集跳到记录尾获得记录数)当记录数据量大时,也会出现类似问题。

可参考其他方法:

解决MVC下分页显示的问题:

http://www.pconline.com.cn/pcedu/empolder/wz/jsp/0507/661142.html

原创粉丝点击