论坛首页 Java企业应用论坛

抛砖引玉,聊下分页。

浏览 6986 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-05-15   最后修改:2013-05-20

好久没逛iteye呢,这两天空闲,聊下分页。
这是我从easyui 和 hibernate 的共同点总结得出的。
其他框架其实完全一样。

先看easyui的请求参数:只有两个。

rows :每页数据行
page: 第几页

 
再看hibernate的参数,也只需要两个。

query.setFirstResult()
query.setMaxResults()

 
所以实际上,任何分页组件只需要两个参数,我们用java类进行封装。

public class Page {
    private int page;
    private int rows;
     ...set.get

      //获取开始行号的函数,还是由page,rows两个参数计算得到
      public int getFirstResult() {
         return (page - 1) * rows;
    }
}

 
一、第一个问题:数据放在哪里?总行数放哪里?有几种方案提供参考:
1、

public class Page {
private int page;
private int rows;
        //数据:作为一个属性放在page里
        private list data;
       //总行数:作为一个属性放在page里
        private int total;

public int computeFirstResult() {
return (page - 1) * rows;
}
}

 2、

public class Grid{
      //分页对象
      private Page page;
      //其他分页相关的对象,比如orderby
     ..........
    
      //数据:作为一个属性放在page里
      private list data;
      //总行数:作为一个属性放在page里
      private int total;
}

 申明一个类,将page,data,total,作为其中一个属性存在。

二、第二个问题:hibernate分页代码如何写。

// 分页查询
public void queryGrid(String sql, Grid grid) {
Session session = sessionFactory.getCurrentSession();

// 总页数
String countSql = select count(*) from(" "+ sql + " ") as TEMP_TOTAL;
Object o = session.createSQLQuery(countSql).uniqueResult();
int total = Integer.valueOf(o.toString());

// 本页数据
Query query = session.createSQLQuery(sql).setResultTransformer(
Transformers.ALIAS_TO_ENTITY_MAP);
query.setFirstResult(grid.getPage().getFirstResult());
query.setMaxResults(grid.getPage().getRows());
List  list = query.list();
               
//设置分页数据、总行数
grid.setData(list);        grid.gePage.setTotal(total); 
}

 应该走出这样的误区:t

1、分页调用两次函数才能完成,看到很多这样的设计。
       一个函数获取total总行数,一个函数获取data的函数。
2、可以参考queryGrid()。
      不一定就需要有返回值。即使有,也不应该是list对象,否则total属性会丢失。

 

三、第三个问题:Page或者Grid对象由谁来创建。
       不应该是业务程序员来创建,肯定是框架来实现。
       也就是说你的业务代码中不应该有下面的代码:

       page.setPage(request.getParmeter());

 
四、第四个问题:分页数据、分页工具栏如何剥离?
1、我用的easyui分页,所以没有自己写代码,相信你一定也可以做到。
2、我只证明说一下:easyui的grid响应只需要两个值:

data:数据
total:总行数

 

    因为easyui是ajax请求数据,只用这以上两参数做出呢下面的分页栏。
    熟悉easyui的朋友可以自我联想。

  
 
  3、实际上可能你还还需要2个参数,也就是第一段代码的2个参数。

page:第几数
rows:每页多少行

 
五、第五个问题:ToolBar和通用性。
       这里用hibernate举例而已,换成jdbc其实也一样。
      easyui的参数可以照搬,不用他的分页组件。

 

1、 所以正宗的分页toolbar应该用js来创建。

      如此简单的事情,不会难倒你的。
2、简单一点的用的方法导入分页jsp页面。
3、最后一点最重要,提供一些思路。

     上一页页码、下一页页码、是否有上一页、下一页等。
     这些是神马概念哪里去呢?
     这些是函数,不是属性值。
     这些函数由上面提到的4个参数计算而出,所以这些最好由前面的Toolbar来做,做成 javascript  函数。   

 4、以最小职责为原则,绝不越位,满足90%功能的Page。

public class Page {
	private int page;
	private int rows;
	private int total;
	private list data;  

	//page.set.get
	//rows.set.get
	//total.set.get
	//data.set.get

	public int computeFirstResult() {
		return (page - 1) * rows;
	}
}

 

一点思路,抛砖引玉,随意吐槽。
工作马上就没呢,悲剧啊。

 

  • 大小: 14.8 KB
   发表时间:2013-05-16  
更关注最后一句,求楼主展开……
0 请登录后投票
   发表时间:2013-05-17  
guyeshenshang 写道

好久没逛iteye呢,这两天空闲,聊下分页。
这是我从easyui 和 hibernate 的共同点总结得出的。
其他框架其实完全一样。

先看easyui的请求参数:只有两个。

rows :每页数据行
page: 第几页

 
再看hibernate的参数,也只需要两个。

query.setFirstResult()
query.setMaxResults()

 
所以实际上,任何分页组件只需要两个参数,我们用java类进行封装。

public class Page {
    private int page;
    private int rows;
     ...set.get

      //获取开始行号的函数,还是由page,rows两个参数计算得到
      public int getFirstResult() {
         return (page - 1) * rows;
    }
}

 
一、第一个问题:数据放在哪里?总行数放哪里?有几种方案提供参考:
1、

public class Page {
private int page;
private int rows;
        //数据:作为一个属性放在page里
        private list data;
       //总行数:作为一个属性放在page里
        private int total;

public int computeFirstResult() {
return (page - 1) * rows;
}
}

 2、

public class Grid{
      //分页对象
      private Page page;
      //其他分页相关的对象,比如orderby
     ..........
    
      //数据:作为一个属性放在page里
      private list data;
      //总行数:作为一个属性放在page里
      private int total;
}

 申明一个类,将page,data,total,作为其中一个属性存在。

二、第二个问题:hibernate分页代码如何写。

// 分页查询
public void queryGrid(String sql, Grid grid) {
Session session = sessionFactory.getCurrentSession();

// 总页数
String countSql = select count(*) from(" "+ sql + " ") as TEMP_TOTAL;
Object o = session.createSQLQuery(countSql).uniqueResult();
int total = Integer.valueOf(o.toString());

// 本页数据
Query query = session.createSQLQuery(sql).setResultTransformer(
Transformers.ALIAS_TO_ENTITY_MAP);
query.setFirstResult(grid.getPage().getFirstResult());
query.setMaxResults(grid.getPage().getRows());
List  list = query.list();
               
//设置分页数据
grid.setData(list);
}

 应该走出这样的误区:

1、分页调用两次函数才能完成,看到很多这样的设计。
       一个函数获取total总行数,一个函数获取data的函数。
2、可以参考queryGrid()。
      不一定就需要有返回值。即使有,也不应该是list对象,否则total属性会丢失。

 

三、第三个问题:Page或者Grid对象由谁来创建。
       不应该是业务程序员来创建,肯定是框架来实现。
       也就是说你的业务代码中不应该有下面的代码:

       page.setPage(request.getParmeter());

 
四、第四个问题:分页数据、分页工具栏如何剥离?
1、我用的easyui分页,所以没有自己写代码,相信你一定也可以做到。
2、我只证明说一下:easyui的grid响应只需要两个值:

data:数据
total:总行数

 

    因为easyui是ajax请求数据,只用这以上两参数做出呢下面的分页栏。
    熟悉easyui的朋友可以自我联想。

  
 
  3、实际上可能你还还需要2个参数,也就是第一段代码的2个参数。

page:第几数
rows:每页多少行

 
五、第五个问题:ToolBar和通用性。
       这里用hibernate举例而已,换成jdbc其实也一样。
      easyui的参数可以照搬,不用他的分页组件。

 

1、 所以正宗的分页toolbar应该用js来创建。

      如此简单的事情,不会难倒你的。
2、简单一点的用的方法导入分页jsp页面。
3、最后一点最重要,提供一些思路。

     上一页页码、下一页页码、是否有上一页、下一页等。
     这些是神马概念哪里去呢?
     这些是函数,不是属性值。
     这些函数由上面提到的4个参数计算而出,所以这些最好由前面的Toolbar来做,做成 javascript  函数。   

 4、以最小职责为原则,绝不越位,满足90%功能的Page。

public class Page {
	private int page;
	private int rows;
	private int total;
	private list data;  

	//page.set.get
	//rows.set.get
	//total.set.get
	//data.set.get

	public int computeFirstResult() {
		return (page - 1) * rows;
	}
}

 

一点思路,抛砖引玉,随意吐槽。
工作马上就没呢,悲剧啊。

 

 

应该走出这样的误区:

Java代码  收藏代码
  1. 1、分页调用两次函数才能完成,看到很多这样的设计。  
  2.        一个函数获取total总行数,一个函数获取data的函数。  
  3. 2、可以参考queryGrid()。  
  4.       不一定就需要有返回值。即使有,也不应该是list对象,否则total属性会丢失。

这句话没明白,分页都是2次查询,一次totalcount,一次分页数据;如果不查询totalcount怎么计算总页数啊??

 

0 请登录后投票
   发表时间:2013-05-18  
同楼上问,分页一直都是两次查询阿?
0 请登录后投票
   发表时间:2013-05-19  
应该说的是调用两次方法吧,我们系统是封装了查询方法,查询全部的是一个,查询分页的是一个方法,然后如果需要分页,程序员调用分页方法,分页方法中自动将threadlocal中的page的参数取得,自动生成查询总页数sql。
0 请登录后投票
   发表时间:2013-05-20  
guyeshenshang 写道

 应该走出这样的误区:

1、分页调用两次函数才能完成,看到很多这样的设计。
       一个函数获取total总行数,一个函数获取data的函数。
2、可以参考queryGrid()。
      不一定就需要有返回值。即使有,也不应该是list对象,否则total属性会丢失。

这两句话意思是两个查询是不对的?

0 请登录后投票
   发表时间:2013-05-20  
分页查询只需要知道两个参数,pageIndex当前第几页,pageSize每页几条数据

返回的时候需要知道总记录数total
所以后台还要查一下总条数select count(*) from table
0 请登录后投票
   发表时间:2013-05-20  
我关注的是分页查询能不能一条sql写出来
0 请登录后投票
   发表时间:2013-05-20   最后修改:2013-05-20

 

// 分页查询
public void queryGrid(String sql, Grid grid) {
Session session = sessionFactory.getCurrentSession();

// 获取总页数:total
String countSql = select count(*) from(" "+ sql + " ") as TEMP_TOTAL;
Object o = session.createSQLQuery(countSql).uniqueResult();
int total = Integer.valueOf(o.toString());

// 获取本页数据:data
Query query = session.createSQLQuery(sql).setResultTransformer(
Transformers.ALIAS_TO_ENTITY_MAP);
query.setFirstResult(grid.getPage().getFirstResult());
query.setMaxResults(grid.getPage().getRows());
List  list = query.list();
               
//设置分页数据
grid.setData(list);                //.....这里传递分页数据
grid.setTotal(total);              //.....这里传递总页数  
}

 

这是针对mysql的,总体思路就一个:

data 和 total 在一个函数内完成。

这条大致我的理解是紧密元素的高内聚。

还是以easyui的数据格式做参考,紧密的list 和 rows形成返回值:

{
	"rows" : [ {
		"name" : "经理",
		"positionId" : 32
	}, {
		"name" : "主管",
		"positionId" : 33
	} ],
	"total" : 7
}

 如果更严格的区分概念,还应该是两个类更明晰化。

分页请求对象,分页响应对象。简单点就整一起呗。

 

 

0 请登录后投票
   发表时间:2013-05-21  

楼主所说两个参数

  • 每页记录数(size)
  • 请求页码(index)

实际应用场景其实还需要两个参数

  • 排序方向(isAsn)
  • 排序字段(column)

建议Page对象包涵这四个参数,以免以后还要添加

至于当前查询结果所包含的记录总数(total)可以用过返回结果的列表长度来获取,无需增加

所以,综上所得

public class PageParam {
  private Intger size;
  private Intger index;
  private Boolean isAsn;
  private String column;

}

 

 

 

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics