jfinal 带group by查询的分页

黄开源中国 发布于 2013/08/02 18:35
阅读 1K+
收藏 0

在model类,paginate方法中

if (size == 1)

totalRow = ((Number)result.get(0)).longValue(); // totalRow = (Long)result.get(0);

else if (size > 1)
totalRow = result.size();

else
return new Page<M>(new ArrayList<M>(0), pageNumber, pageSize, 0, 0); // totalRow = 0;

totalPage = (int) (totalRow / pageSize);
if (totalRow % pageSize != 0) {
totalPage++;
}


这段有点问题。

假如有个user 表,表里面有id, sex两个字段

我用select count(*) from user group by sex

假如表中有多于一种sex取值是没问题的。。但是当只有一种sex取值的时候,返回就会变成是count(*)的数量。这样很明显是不正确。。。会多出一页。。(totalPage++;这一行。

想把源码里面的那一句

if (size == 1)

totalRow = ((Number)result.get(0)).longValue(); // totalRow = (Long)result.get(0);这一句去掉。但是不知道是不是有什么特定的应用场景。。麻烦用过的朋友帮忙解答一下。谢谢@jfinal

加载中
1
宏哥
宏哥

回复 @JFinal

/**
	 * Gettting Sorted paginated page from Orignal SQL
	 *
	 * @param Array $headers, The selected column and labels, not show when label not set 
	 * @param String $sql SQL query without select
	 * @param UTL Object &$page UTL object of tempalte
	 * @param Array $sortBy Order by column, 'o'=> Order by String, 's' => Sorting order 
	 * @param String $dataPro Data Property Name, default 'data'
	 * @param String $pagePro Pagnation Frament property Name, default 'pagination'
	 * @param String $perpagePro  Perpage property
	 * @param String $curpagePro  Current Page property
	 * @param String $db Database Instance Name, default 'default'
	 * @param Boolean $as_object Populate Data as Object if TRUE, default TRUE
	 * @return True if success
	 */

	public static function getSortedPage(array &$headers,$_fromsql,&$page,Array $sortBy,$dataPro='data',$headerPro='headers',
		$pagePro='pagination', $perpagePro='perpage',$curpagePro='page',$db = 'default',$as_object=true){
			$config = array();
			$config['items_per_page']['key'] = $perpagePro;
			//$config['items_per_page']['value'] =10;
			$_pconfig = Pexcel::config('pagination.default');
			$config['items_per_page']['value'] =$_pconfig['items_per_page']['value'];
			if(isset($_GET[$perpagePro])){
				$config['items_per_page']['value'] = $_GET[$perpagePro];
			}

			if($curpagePro){
				$config['current_page'] = array('source'=>'query_string','key'=>$curpagePro);
			}

			$cols = self::getCols($headers);

			$_sql = 'select '.DB::quote_column($cols,$db).' '.$_fromsql;

			$_o = Arr::get($sortBy,'o','updated');
			$_s = Arr::get($sortBy,'s','desc');

			$_orderBy = DB::quote_column($_o).' '.$_s;
			foreach ($headers as $col => &$header){
				//Remove sort for header
				$_sort = Arr::get($header,'sort',TRUE);
				$header['sort'] = $_sort;

				$_format = Arr::get($header,'format',self::FMT_STRING);
				$header['format'] = $_format;

				if($_sort){
					if( $col != $_o){ //Default Link is 
						$header['url'] = URL::query(array('o'=>$col,'s'=>'desc'));
						$header['class'] = 'sortIcon';
					}else{
						if($_s == 'desc'){
							$header['url'] = URL::query(array('o'=>$col,'s'=>'asc'));
							$header['class'] = 'sortIcon sortDesc';
						}else{
							$header['url'] = URL::query(array('o'=>$col,'s'=>'desc'));
							$header['class'] = 'sortIcon sortAsc';
						}
					}
				}
			}

			$page->{$headerPro}= $headers;
			return self::getPage($_sql,$page,$_orderBy,$dataPro,$pagePro,$config,$db,$as_object);
		}
/**
	 * Gettting paginated page from Orignal SQL
	 *
	 * @param String $sql SQL query
	 * @param UTL Object &$page UTL object of tempalte
	 * @param String $orderBy Order by column, default 'updated desc'
	 * @param String $dataPro Data Property Name, default 'data'
	 * @param String $pagePro Pagnation Frament property Name, default 'pagination'
	 * @param Array $config  Pagination Configuration Array overider
	 * @param String $db Database Instance Name, default 'default'
	 * @param Boolean $as_object Populate Data as Object if TRUE, default TRUE
	 * @param String $_paginClass Class Name of pagination 
	 * @return True if success
	 */
	public static function getPage($_sql,&$page,$orderBy ='updated desc', $dataPro='data',$pagePro = 'pagination',
		$config = NULL,$db = 'default',$as_object= true,$_paginClass='Pagination'){

			$_csql = 'select count(1) as c from ('.$_sql.') st'; 
			$_c  = DB::query(self::SELECT,$_csql)->execute($db)->get('c');

			if($config){
				$config['total_items'] = $_c;
				$_pagination = new $_paginClass($config);
			}else{
				$config = array();
				$config['total_items'] = $_c;
				$_pagination = new $_paginClass($config);
			}

			$_sql .= ' order by '.$orderBy;

			if($_pagination->offset){
				$_sql .= ' offset '.$_pagination->offset;
			}
			$_sql .= ' limit '.$_pagination->items_per_page;

			$_data = DB::query(self::SELECT,$_sql,$as_object)->execute($db)->as_array();
			if(!$_data){
				$page->{$dataPro} = false;
				$page->{$pagePro} = false;
				return false;	
			}

			$page->{$dataPro} = $_data;
			$page->{$pagePro} = $_pagination;
			return true;
		}

JFinal
JFinal
开发 jfinal 1.6 版的时候参考下,多谢支持 :)
0
JFinal
JFinal
if (size == 1) 是为了处理没有使用 group by的情况,去掉后会有问题,调试一下就知道了
JFinal
JFinal
回复 @黄开源中国 : 你这种情况我需要验证一下,jfinal 1.6 已经做了备忘
黄开源中国
黄开源中国
那请问下我的这种情况算是代码的一个BUG吗?还是说我的sql语句写的有问题?
0
j
jeff_ding

我也碰到了这个问题,把源码改成如下就好了,@jfinal

  if (size == 1 && sqlExceptSelect.toLowerCase().indexOf("group by") < 0)
   totalRow = ((Number)result.get(0)).longValue();
  else if (size > 0)
   totalRow = result.size();

 

0
光石头
光石头
totalRow = result.size(); 本身就是一个坑,如果group by后有10w条数据,等同把10w条数据加载到内存,取值一个result.size().我刚看一下,jfinal 1.5 竟然还没有处理这个问题.
黄开源中国
黄开源中国
是的。专门看了1.5的说明。没看到解决这个问题。而且对于pagenum也没处理。。就是譬如原来的页码是11/15页,但是请求的时候由于数据的增减可能末页 已经变成7了。。那么当请求11的时候,paginate函数里面不会根据count(*)的结果跟传入的pagenum进行比较。。
0
宏哥
宏哥

引用来自“屁屁果”的答案

totalRow = result.size(); 本身就是一个坑,如果group by后有10w条数据,等同把10w条数据加载到内存,取值一个result.size().我刚看一下,jfinal 1.5 竟然还没有处理这个问题.

楼上是懂数据库的

宏哥要求 @jFinal 尽快修复此BUG

分页必须 count(*) 单独的语句来计算总数

JFinal
JFinal
目前正是用的count(*),楼主提出的是因为group by 引发的问题,开发下一版时会进行验证,不知道 @宏哥 有何高见,php 下做分页是如何写的sql
黄开源中国
黄开源中国
希望@jFinal大大能关注到这个问题哈~
返回顶部
顶部