WEB工程分页技术实现
在web项目中主要有以下两种分页的方式:
- 假分页
- 真分页
-假分页方法:
基于List的分页,将全部查询结果先放到一个大的List中,然后调用List提供的subList()方法,从大的List中截取一小段显示在页面上。该方法将数据全部查询放入List,对内存消耗有点大,仅适用于少量数据。
- 真分页方法:
1.基于DB的分页:在SQL查询语句中,只将符合条件的查询结果放入ResultSet,然后再将ResultSet中的数据封装,显示在页面上。
2.基于ResultSet的分页:首先个人猜测,ResultSet并没有将符合查询条件的全部信息放入内存,而只是装载了每条数据的rowid。
基于ResultSet的分页步骤:(1)执行查询语句rs=pstm.executeQuery();(2)将rs指针定位到结果集的最后一行:rs.last();(3)获取结果的条数:int rowcount=rs.getRow();(4)总的页面数的计算:int countpage=(rowcount+pagesize-1)/pagesize; pagesize表示每个页面显示的结果条数
详细代码:
/**
* 分页查询的实现
* @param sql
* @param pagesize --- 每页的行数
* @param val
* @return
* @throws Exception
*/
protected final List<Map<String,String>> queryForList(String sql,int pagesize,Object...val)throws Exception
{
//1.定义JDBC变量
PreparedStatement pstm=null;
ResultSet rs=null;
try
{
/**
* pstm生成rs结果集.默认情况下,只能每次向下滚动一行数据
* ResultSet.TYPE_SCROLL_SENSITIVE, 让rs可以双向滚动
* ResultSet.CONCUR_READ_ONLY rs中查询到的数据,以只读方式并发访问
* rs当前查询到的数据,在rs读取完毕以前,其他程序不能更新
*/
pstm=DBUtils.prepareStatementPage(sql);
//参数赋值
int index=1;
for(Object param:val)
{
pstm.setObject(index++, param);
}
//执行查询
rs=pstm.executeQuery();
/********************************************************
* 总页码计算
********************************************************/
//计算总行数
rs.last(); //将rs指针直接定位到查询结果的最后一行
//获取总行数
int rowcount=rs.getRow(); //37
//总页码计算
int countPage=(rowcount+pagesize-1)/pagesize;
//将总页面赋值给属性
this.countPage=countPage;
/********************************************************
* 当前可获取页码计算
********************************************************/
//当前可获取页码计算
int currentPageNumber=1;
Object getPageNum=this.dto.get("query");
if(getPageNum!=null && !getPageNum.equals(""))
{
currentPageNumber=Integer.parseInt(getPageNum.toString());
}
//如果传入的当前页码比总的页数大,那么获取最后页
if(currentPageNumber>countPage)
{
currentPageNumber = countPage;
}
//为当前页码属性赋值
this.current_page=currentPageNumber;
/*************************************************
* 计算当前页码的起始行数[算法:(当前页码-1)*每页行数)]
*************************************************/
int startRow=(currentPageNumber-1)*pagesize;
if(startRow<1)
{
rs.beforeFirst(); //将rs的指针定位到第一行记录之前,也就是指针归位算法
//rs.first(); //将指针定位到查询结果的第一行
}
else
{
//rs绝对行数定位方法---将rs的指针直接定位到某一行
rs.absolute(startRow);
}
/**********************************************************
* 获取当前页数据
**********************************************************/
//获取rs描述对象
ResultSetMetaData rsmd=rs.getMetaData();
//获取列数
int count=rsmd.getColumnCount();
//计算初始容量
int init_size=((int)(count/.75))+2;
//定义装载当前页数据的List对象
List<Map<String,String>> rows=new ArrayList<>(pagesize);
//定义装载当前行数据的Map
Map<String,String> ins=null;
//通过双层for循环解析数据
for(int i=1;i<=pagesize;i++) //5
{
//判断数据是否存在
if(rs.next())
{
//实例化ins装载当前行数据
ins=new HashMap<>(init_size);
//解析当前行所有列
for(int j=1;j<=count;j++)
{
ins.put(rsmd.getColumnLabel(j).toLowerCase(), rs.getString(j));
}
//将当前行数据放入List
rows.add(ins);
}
else
{
break;
}
}
return rows;
}
finally
{
DBUtils.close(rs);
DBUtils.close(pstm);
}
}