`
xugq035
  • 浏览: 36067 次
社区版块
存档分类
最新评论

一个通用分页查询方法

    博客分类:
  • J2EE
 
阅读更多
为了简化开发人员的代码,想写一个通用的分页查询方法,为了提交效率,其中有一段是分解hql语句,组成查询总数的hql语句,实现如下:
	public PaginationSupport findPageByQuery(final String hsql,final Object[] values,
			final int pageSize, final int startIndex) {
		return (PaginationSupport) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String totalSql=null;
						if(hsql.toUpperCase().indexOf("SELECT")==-1)
							totalSql="SELECT COUNT(*) "+hsql.split("order by")[0].split("ORDER BY")[0];
						else if(hsql.toUpperCase().split("SELECT").length==2){
							totalSql=hsql.split("order by")[0].split("ORDER BY")[0];
							String[] tt=totalSql.split(" ");
							String colStr="",subStr="";int flag=1;
							for(int i=0;i<tt.length;i++){
								if(tt[i].equalsIgnoreCase("select"))continue;
								else if(tt[i].equalsIgnoreCase("from")){flag=2; continue;}
								else if(flag==1)colStr+=" "+tt[i];
								else subStr+=" "+tt[i];
							}
							totalSql="SELECT COUNT("+colStr.split(",")[0]+") FROM "+subStr;
						}
						Query totalQuery=null;
						if(totalSql!=null){
							totalQuery=session.createQuery(totalSql);
						}
						Query query = session.createQuery(hsql);
						if (values != null) {
	                        for (int i = 0; i < values.length; i++) {
	                        	if(totalQuery!=null) totalQuery.setParameter(i, values[i]);	                        	query.setParameter(i, values[i]);
	                        }
	                    }
						int totalCount=-1;
						if(totalQuery==null){
							if(pageSize>0)totalCount=query.list().size();
						}else{
							Object o=totalQuery.list().get(0);
							totalCount = (o==null?0:Integer.parseInt(o+""));
						}						if(startIndex>0) query.setFirstResult(startIndex);
						if(pageSize>0) query.setMaxResults(pageSize);

						List items = query.list();
						if(totalCount==-1) totalCount=items.size();
						PaginationSupport ps = new PaginationSupport(items,
								totalCount, pageSize, startIndex);
						return ps;

					}
				}, true);
	}



但是,在这个统计总数的hql会有问题,当数据表的主键包含多个字段的时候,最后生成的sql会变成count(pid,did),这样就会导致错误,如果有distinct时会更复杂,count(distinct pid,did),现在我只能添加个try,出现异常时调用query.list().size()去获取总数
对于通用的分页查询方法各位有什么好办法?
分享到:
评论
21 楼 sp42 2015-05-18  
douban
20 楼 xugq035 2009-08-17  
h521999 写道
建议lZ看看springside,学习一下SpringSide的分页方法吧.


多谢,以下是springside的源码。本质是一样,只是代码的优雅程度和处理方式有差别
    /**
     * HQL分页查询,可以指定具体的模式,
     * 采用getCount方式,须在此层完成hsql的转换与查询。
     * 注意参数Object...args的应用,可以在查询的设置查询条件用的(JDK5.0语法)
     */
    public Page pagedQuery(String hql, int pageNo, int pageSize, Object... args) {
        Assert.hasText(hql);
        Query query = getSession().createQuery(hql);
        for (int i = 0; i < args.length; i++) {
            query.setParameter(i, args[i]);
        }
            String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
            List countlist = getHibernateTemplate().find(countQueryString, args);
            int totalCount = (Integer) countlist.get(0);
            return HqlPage.getPageInstanceByCount(query, pageNo, pageSize, totalCount);
    }

    /**
     * 去除select 子句,未考虑union的情况
     */
    private static String removeSelect(String hql) {
        Assert.hasText(hql);
        int beginPos = hql.toLowerCase().indexOf("from");
        Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
        return hql.substring(beginPos);
    }

    /**
     * 去除orderby 子句
     */
    private static String removeOrders(String hql) {
        Assert.hasText(hql);
        Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(hql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }
19 楼 xugq035 2009-08-17  
kjj 写道
感觉是把简单的事情复杂化!!!


这里的封装是复杂了,为的是给其他开发人员方便调用
18 楼 xugq035 2009-08-17  
grave 写道
xugq035 写道
jltest 写道
既然用hql还分解什么hql语句。明明就有现成的方法


可能你没看清我的主题,我的目的是“为了简化开发人员的代码”

也就是说开发人员作查询时只需要编写:
PaginationSupport findUser(){
  return findPageByQuery("from user",null,20,0);
}

就可以了,返回的是 PaginationSupport,里面封装了分页需要的数据,其中一项就是数据总数,所以要求对输入的hql语句作拆分

不得不说还是用criteria api吧


criteria我也封装了一个,这个处理好点,用rowCount()).uniqueResult()即可得到总数

	public PaginationSupport findPageByCriteria(
			final DetachedCriteria detachedCriteria, final int pageSize,
			final int startIndex) {
		return (PaginationSupport) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						int totalCount = ((Integer) criteria.setProjection(
								Projections.rowCount()).uniqueResult())
								.intValue();
						criteria.setProjection(null);
						List items = criteria.setFirstResult(startIndex)
								.setMaxResults(pageSize).list();
						PaginationSupport ps = new PaginationSupport(items,
								totalCount, pageSize, startIndex);
						return ps;
					}
				}, true);
	}
17 楼 src_bord 2009-08-17  
   这种做法挺好的 呵呵~把分页的变量多封装在一个pages类里边  这一来在页面就要省好多事了~
16 楼 grave 2009-08-16  
xugq035 写道
jltest 写道
既然用hql还分解什么hql语句。明明就有现成的方法


可能你没看清我的主题,我的目的是“为了简化开发人员的代码”

也就是说开发人员作查询时只需要编写:
PaginationSupport findUser(){
  return findPageByQuery("from user",null,20,0);
}

就可以了,返回的是 PaginationSupport,里面封装了分页需要的数据,其中一项就是数据总数,所以要求对输入的hql语句作拆分

不得不说还是用criteria api吧
15 楼 inputer 2009-08-16  
这样的代码懒散的我,没办法看下去了.
14 楼 h521999 2009-08-16  
建议lZ看看springside,学习一下SpringSide的分页方法吧.
13 楼 kjj 2009-08-16  
感觉是把简单的事情复杂化!!!
12 楼 xugq035 2009-08-16  
我举的这个例子findUser返回的是一个PaginationSupport对象,里面封装了总数、数据、开始记录、每页记录数等。可能改称findUserList这样会容易看一些
至于这个代码不好看,现在我想到的只有拆hql语句的办法,开这个贴就是为了把需求提出来探讨一下有哪些更好的方法
11 楼 dch1287 2009-08-16  
findUser 返回的不是 User or Users ?

代码写的 真的不好看 。。

hql分页怎么会封装得如此 。。

为什么同样的回复要submit这么多次 ?
10 楼 xugq035 2009-08-15  
myworkfirst 写道
  hq 还要自己写分页吗? 都提供了分页机制。


我这里就是利用了分页机制封装了一下,方便下面的程序员调用

也就是说开发人员作查询时只需要编写:
PaginationSupport findUser(){
  return findPageByQuery("from user",null,20,0);
}
返回的是 PaginationSupport,里面封装了分页需要的数据,其中一项就是数据总数
9 楼 xugq035 2009-08-15  
317082755 写道
这样的分页没必要写啊


可能你没看清我的主题,我的目的是“为了简化开发人员的代码”

也就是说开发人员作查询时只需要编写:
PaginationSupport findUser(){
  return findPageByQuery("from user",null,20,0);
}
就可以了,返回的是 PaginationSupport,里面封装了分页需要的数据,其中一项就是数据总数,所以要求对输入的hql语句作拆分
8 楼 xugq035 2009-08-15  
sjynt131 写道
统一取list.size()吧


从后台输出的sql语句看这样其实是作了一次查询所有记录的操作,比较耗资源;我的想法是改为count效率会高很多
7 楼 xugq035 2009-08-15  
flysunsystem 写道
浪费手续。就这样个方法还通用?个人认为最好的办法就是建立一个Page对象。有不明白的可以问。


可能你没看清我的主题,我的目的是“为了简化开发人员的代码”

也就是说开发人员作查询时只需要编写:
PaginationSupport findUser(){
  return findPageByQuery("from user",null,20,0);
}

就可以了,返回的是 PaginationSupport就是你说的一个Page对象,里面封装了分页需要的数据,其中一项就是数据总数,所以要求对输入的hql语句作拆分

另外,应该你有不明白的可以问~~
6 楼 xugq035 2009-08-15  
jltest 写道
既然用hql还分解什么hql语句。明明就有现成的方法


可能你没看清我的主题,我的目的是“为了简化开发人员的代码”

也就是说开发人员作查询时只需要编写:
PaginationSupport findUser(){
  return findPageByQuery("from user",null,20,0);
}

就可以了,返回的是 PaginationSupport,里面封装了分页需要的数据,其中一项就是数据总数,所以要求对输入的hql语句作拆分
5 楼 myworkfirst 2009-08-11  
  hq 还要自己写分页吗? 都提供了分页机制。
4 楼 317082755 2009-08-11  
这样的分页没必要写啊
3 楼 sjynt131 2009-08-10  
统一取list.size()吧
2 楼 flysunsystem 2009-08-10  
浪费手续。就这样个方法还通用?个人认为最好的办法就是建立一个Page对象。有不明白的可以问。

相关推荐

    基于C++开发的WEB服务器,支持C/C++、Python、Java等多语言混合开发WEB应用

    基于C++开发的WEB服务器,支持C/C++、Python、Java等多语言混合开发WEB应用

    基于STM8单片机的TM1615七段数码管驱动(模拟I2C).zip

    基于STM8单片机的编程实例,可供参考学习使用,希望对你有所帮助

    基于STM8单片机的电位器输入控制继电器输出实验.zip

    基于STM8单片机的编程实例,可供参考学习使用,希望对你有所帮助

    网络安全CTF靶场之rce-labs

    该靶场仅供学习使用!

    python爬虫豆瓣电影TOP250,以及数据化分析程序源代码+数据

    电影详情链接 图片链接 影片中文名 影片外国名 评分 评价人数 概况 相关信息 https://movie.douban.com/subject/1292052/ https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg 肖申克的救赎   The Shawshank Redemption 9.7 2529468 希望让人自由 导演: 弗兰克·德拉邦特 Frank Darabont   主演: 蒂姆·罗宾斯 Tim Robbins ... 1994   美国   犯罪 剧情 https://movie.douban.com/subject/1291546/ https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2561716440.jpg 霸王别姬 9.6 1880353 风华绝代 导演: 陈凯歌 Kaige Chen   主演: 张国荣 Leslie Cheung 张丰毅 ........

    汽车中间件市场调研报告:2023年全球汽车中间件市场销售额达到了78亿美元

    汽车中间件市场调研报告:2023年全球汽车中间件市场销售额达到了78亿美元 在数字化转型的浪潮中,汽车中间件作为连接硬件与软件的关键桥梁,正引领着汽车行业的新一轮变革。随着全球汽车产业的快速发展,中间件市场规模持续扩大,展现出前所未有的增长潜力。然而,面对复杂多变的市场环境和不断涌现的新技术,企业如何精准把握市场脉搏,实现可持续发展?本文将深入探讨全球及中国汽车中间件市场的现状、趋势及竞争格局,为您揭示咨询的重要性。 市场概况: 根据QYResearch(恒州博智)的统计及预测,2023年全球汽车中间件市场销售额达到了78亿美元(约7803百万美元),预计2030年将达到156亿美元(约15630百万美元),年复合增长率(CAGR)为10.3%(2024-2030)。这一数据不仅彰显了中间件市场的强劲增长动力,也预示着未来巨大的市场空间。 技术创新与趋势: 随着自动驾驶、车联网等技术的不断发展,汽车中间件正面临着前所未有的技术挑战与机遇。新一代中间件需要具备更高的实时性、更低的延迟以及更强的数据处理能力,以满足复杂多变的汽车应用场景。同时,云计算、大数据、人工智能等技术的融合应用,将进

    python语言mp3pl爬虫程序代码QZQ.txt

    python语言mp3pl爬虫程序代码QZQ

    小语种字体TTF文件转PNG图片的方法

    # 小语种字体TTF文件转PNG图片的方法 ## 准备工作 1. 下载python3.9,推荐3.6~3.9,几个依赖包在这个版本运行的好。 2. 下载 FontForge-mingw-w64 ,可自行下载,或从文末打包好的工具包直接使用。 3. 下载需要导出的字体ttf文件,最好先装在本机系统上。 ## 导出方法 1. 把 `tts2png2.py` 文件复制到软件的bin目录下。 2. 修改 `tts2png2.py` 文件中的字体路径,注意Windows用双斜杠。 3. 从bin目录打开终端(管理员模式启动)。 4. 运行脚本 `./ffpython .\tts2png2.py`。

    26页-基于AI人工智能的智慧校园综合解决方案AI+智慧校园综合解决方案.pdf

    在21世纪的科技浪潮中,人工智能(AI)无疑是最为耀眼的明星之一,它以惊人的速度改变着我们的生活、工作乃至整个社会的运行方式。而在人工智能的广阔领域中,大模型(Large Models)的崛起更是开启了智能技术的新纪元,引领着AI向更加复杂、高效、智能的方向发展。本文将深入探讨人工智能大模型的内涵、技术特点、应用领域以及对未来的影响。 一、人工智能大模型的内涵 人工智能大模型,顾名思义,是指具有庞大参数规模和数据处理能力的AI模型。这些模型通过深度学习算法,在海量数据上进行训练,能够学习到丰富的知识表示和复杂的模式识别能力。与传统的小型或中型模型相比,大模型在理解自然语言、生成高质量内容、进行跨模态信息处理等方面展现出前所未有的优势。它们不仅能够执行特定的任务,如图像识别、语音识别,还能进行创造性的工作,如文本生成、音乐创作,甚至在某些情况下展现出接近或超越人类的智能水平。 二、技术特点 海量数据与高效训练:大模型依赖于庞大的数据集进行训练,这些数据涵盖了广泛的主题和情境,使得模型能够学习到丰富的语义信息和上下文理解能力。同时,高效的训练算法和硬件加速技术,如TPU(Tensor Processing Unit)和GPU,使得大规模模型的训练成为可能。 自注意力机制与Transformer架构:许多领先的大模型采用了Transformer架构,特别是其自注意力机制,这种设计使得模型在处理序列数据时能够捕捉到长距离依赖关系,极大地提高了模型的表达能力和泛化能力。 多任务学习与迁移学习:大模型通常具备多任务学习的能力,即在一次训练中同时学习多个任务,这有助于模型学习到更通用的知识表示。此外,迁移学习使得这些模型能够轻松适应新任务,只需少量额外数据或微调即可。

    下垂控制-基于T型三电平逆变器的下垂控制,电压电流双闭环,采用LCL滤波,SPWM调制方式 1.提供simulink仿真源文件 2.提供下垂控制原理与下垂系数计算方法 3.中点平衡控制,电压电流双闭环

    下垂控制-基于T型三电平逆变器的下垂控制,电压电流双闭环,采用LCL滤波,SPWM调制方式 1.提供simulink仿真源文件 2.提供下垂控制原理与下垂系数计算方法 3.中点平衡控制,电压电流双闭环控制 4.提供参考文献

    一个仿大众点评、美团的城市选择器,使用如同Rx一样优雅,并且UI和城市数据可以自定义.zip

    城市选择器一个仿大众点评的城市快速选择器, 最少只需 一行 代码即可启动城市选择器, 支持页面样式修改,多元化自定义截屏 版本日志V0.4.6优化地理位置设置时有时会设置不成功问题修复其他若干问题修改UI默认主题色V0.4.5修改设置位置信息方式,由之前必须在打开页面之前获取位置信息改为允许用户在打开页面后设置位置信息,具体使用方式见 Step3简化配置项,不需要在AndroidManifest中再注册Activity,并默认隐藏titlebarV0.4.3修复更新数据库表结构后第一次进入会闪退问题V0.4.0数据库表结构修改,增加了高德地图citycode设置gps城市的api略有改动见 Step3V0.3.3紧急修复一个可能导致内存泄漏问题优化提高滑动检索效率隐藏下拉刷新labelV0.3.1在搜索框后面添加一个清空搜索框按钮修复搜索框中输入空格会搜索出全部城市问题修复搜索结果弹出框中文字在不同theme下显示不同颜色问题,现在已统一为黑色其他调用时参数合法性校验V0.3.0简化api调用形式,修改为Rx形式,见操作步骤

    慢性病大数据分析处理.zip

    慢性病大数据分析处理慢性病项目

    Multisim单片机资源单片机C语言程序设计实训100例

    Multisim单片机资源单片机C语言程序设计实训100例提取方式是百度网盘分享地址

    PMSM永磁同步电机最大转矩电流比MTPA控制仿真,弱磁控制仿真,前馈补偿仿真程序,详细解析教程文档 这是一份非常完美的仿真文件及详细教程,从仿真效果图看转速、电流及转矩跟随非常稳定 该算法架构包

    PMSM永磁同步电机最大转矩电流比MTPA控制仿真,弱磁控制仿真,前馈补偿仿真程序,详细解析教程文档。 这是一份非常完美的仿真文件及详细教程,从仿真效果图看转速、电流及转矩跟随非常稳定。 该算法架构包含如下模块: 1)SVPWM矢量控制模块 2)转速环PI调节器、电流环PI调节器; 3)MTPA调节器; 4)弱磁控制器; 5)前馈补偿; 一份该仿真的算法说明文档,每一步都有详细介绍如何搭建,包括环路参数怎么算,拿来做毕设或者学习都很方便; 几篇参考文献; 一篇作者自己写的算法总结,让你少走弯路; 两个视频;

    手绘卡通儿童人物幼儿园教学课件模板.pptx

    手绘卡通儿童人物幼儿园教学课件模板

    Simulink电动汽车仿真模型(包含行驶阻力模型,工作模式切模型,驾驶员模型,PID控制模块等,NEDC,CLTC工况仿真结果)东西很全

    Simulink电动汽车仿真模型(包含行驶阻力模型,工作模式切模型,驾驶员模型,PID控制模块等,NEDC,CLTC工况仿真结果)东西很全

    2-Perfect Backup v3.3.0 全功能备份神器,支持多种备份方式,免费使用,可商用

    是一款全功能的备份软件,支持增量备份、差异备份、完全备份和同步备份,帮助用户轻松保护关键文件。支持多种存储选项,包括本地硬盘、USB驱动器、网络文件夹、云存储和 FTP 服务器等。 【使用方法】: 1. 下载并安装 Perfect Backup。 2. 打开软件,选择备份类型(增量、差异、完全或同步)。 3. 指定源文件和目标存储位置。 4. 设置备份计划,选择备份频率。 5. 点击“开始备份”,执行备份任务。

    基于STM8单片机的光敏电阻模拟量ADC输入(带中断).zip

    基于STM8单片机的编程实例,可供参考学习使用,希望对你有所帮助

    HTML5实现好看的创意房屋设计公司网页源码.zip

    资源描述: HTML5实现好看的创意房屋设计公司网页源码,好看的创意房屋设计公司网页源码,创意房屋设计公司网页源码模板,HTML创意房屋设计公司网页源码,内置酷炫的动画,界面干净整洁,页面主题,全方位介绍内容,可以拆分多个想要的页面,可以扩展自己想要的,注释完整,代码规范,各种风格都有,代码上手简单,代码独立,可以直接运行使用。也可直接预览效果。 资源使用: 点击 index.html 直接查看效果

Global site tag (gtag.js) - Google Analytics