`
gaogengzhi
  • 浏览: 106025 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Hibernate分页查询小结

阅读更多
通常使用的Hibernate通常是三种:hql查询,QBC查询和QBE查询:
1、QBE(Qurey By Example)检索方式
QBE是最简单的,但是功能也是最弱的,QBE的功能不是特别强大,仅在某些场合下有用。一个典型的使用场合就是在查询窗口中让用户输入一系列的查询条件,然后返回匹配的对象。QBE只支持=和like比较运算符,无法不大区间值,及其或的匹配。在这种情况下,还是采用HQL检索方式或QBC检索方式。
	/**
	 * @function 根据传递过来的Object,分页显示在数据库中与其匹配的记录
	 * @param pageNo
	 *            当前页数
	 * @param pageSize
	 *            每页显示的记录数
	 * @param object
	 *            将查询条件封装为Object
	 * @return 将查询结果封装为Pager返回
	 */
	public Pager findPageByExample(int pageNo, int pageSize, Object object)
	{
		Pager pager = null;
		try
		{
			Criteria criteria = this.getSession().createCriteria(
					Class.forName(this.getEntity()));

			if (object != null)
			{
				criteria.add(Example.create(object).enableLike());
			}

			// 获取根据条件分页查询的总行数
			int rowCount = (Integer) criteria.setProjection(
					Projections.rowCount()).uniqueResult();
			criteria.setProjection(null);

			criteria.setFirstResult((pageNo - 1) * pageSize);
			criteria.setMaxResults(pageSize);

			List result = criteria.list();

			pager = new Pager(pageSize, pageNo, rowCount, result);

		} catch (RuntimeException re)
		{
			throw re;
		} finally
		{
			return pager;
		}

	}

注意代码的第20行,即criteria.add(Example.create(object).enableLike());这一行,需将Example.create(object)调用.enableLike()方法,不然不能模糊查询。
在BO层将需要模糊查询的列用"%%"串起来,不然仍然和"="一样。
BO层代码:
	/**
	 * @function 将传递过来的参数封装成抢修人员Bean,分页查询符合条件的记录
	 * @param pageNo
	 *            当前的页码
	 * @param pageSize
	 *            每页显示的记录数
	 * @param mendName
	 *            抢修人员的名称
	 * @param specialty
	 *            抢修人员的工种
	 * @param post
	 *            抢修人员的职称
	 * @return 将符合条件的记录数以及页码信息封装成PagerBean返回
	 */
	public Pager getInfoByQuery(int pageNo, int pageSize, String mendName,
			String specialty, String post)
	{

		EicMend eicMend = new EicMend();
		if (mendName != null && mendName.length() > 0)
		{
			eicMend.setMendname("%" + mendName + "%");
		}
		if (specialty != null && specialty.length() > 0)
		{
			eicMend.setSpecialty(specialty);
		}
		if (post != null && post.length() > 0)
		{
			eicMend.setPost(post);
		}

		Pager pager = erpManagerDao
				.findPageByExample(pageNo, pageSize, eicMend);
		return pager;
	}

执行SQL语句如下:
Hibernate: select count(*) as y0_ from YJZX.EIC_MEND this_ where 
(this_.MENDNAME like ? and this_.POST like ?)

Hibernate: select * from ( select this_.MENDID as MENDID23_0_, ……
this_.EXPERTREMARK as EXPERTR28_23_0_ from YJZX.EIC_MEND this_ where 
(this_.MENDNAME like ? and this_.POST like ?) ) where rownum <= ?

所以只需将需模糊查询的列用“%%”链接即可。

2、QBC(Qurey By Criteria)检索方式
       采用HQL检索方式时,在应用程序中需要定义基于字符串形式的HQL查询语句。QBC API提供了检索对象的另一种方式,它主要由Criteria接口、Criterion接口和Restrictions接口组成,它支持在运行时动态生成查询语句。比较常见的是两种传参方式:一种是用map传参,另一种是用Criterion…不定参数传参。
Map传参方式范例如下:
DAO层:
	/**
	 * @function 分页显示符合所有的记录数,将查询结果封装为Pager
	 * @param pageNo
	 *            当前页数
	 * @param pageSize
	 *            每页显示的条数
	 * @param map
	 *            将查询条件封装为map
	 * @return 查询结果Pager
	 */
	public Pager findPageByCriteria(int pageNo, int pageSize, Map map)
	{
		Pager pager = null;
		try
		{
			Criteria criteria = this.getSession().createCriteria(
					Class.forName(this.getEntity()));

			if (map != null)
			{
				Set<String> keys = map.keySet();
				for (String key : keys)
				{
					criteria.add(Restrictions.like(key, map.get(key)));
				}
			}

			// 获取根据条件分页查询的总行数
			int rowCount = (Integer) criteria.setProjection(
					Projections.rowCount()).uniqueResult();
			criteria.setProjection(null);

			criteria.setFirstResult((pageNo - 1) * pageSize);
			criteria.setMaxResults(pageSize);

			List result = criteria.list();

			pager = new Pager(pageSize, pageNo, rowCount, result);

		} catch (RuntimeException re)
		{
			throw re;
		} finally
		{
			return pager;
		}

	}

Map传参方式对应BO层代码:
	/**
	 * @function 将传递过来的参数封装成抢修人员Bean,分页查询符合条件的记录
	 * @param pageNo
	 *            当前的页码
	 * @param pageSize
	 *            每页显示的记录数
	 * @param mendName
	 *            抢修人员的名称
	 * @param specialty
	 *            抢修人员的工种
	 * @param post
	 *            抢修人员的职称
	 * @return 将符合条件的记录数以及页码信息封装成PagerBean返回
	 */
	public Pager getInfoByQuery2(int pageNo, int pageSize, String mendName,
			String specialty, String post)
	{

		Map map = new HashMap();

		if (mendName != null && mendName.length() > 0)
		{
			map.put("mendname", "%" + mendName + "%");
		}
		if (specialty != null && specialty.length() > 0)
		{
			map.put("specialty", specialty);
		}
		if (post != null && post.length() > 0)
		{
			map.put("post", post);
		}

		Pager pager = erpManagerDao.findPageByCriteria(pageNo, pageSize, map);
		return pager;
	}

第二种方式:Criterion…不定参数传参方式。其代码如下所示:
DAO层代码:
	/**
	 * @function 分页显示符合所有的记录数,将查询结果封装为Pager
	 * @param pageNo
	 *            当前页数
	 * @param pageSize
	 *            每页显示的条数
	 * @param criterions
	 *            不定参数Criterion
	 * @return 查询结果Pager
	 */
	public Pager findPageByCriteria(int pageNo, int pageSize,
			Criterion... criterions)
	{
		Pager pager = null;
		try
		{
			Criteria criteria = this.getSession().createCriteria(
					Class.forName(this.getEntity()));
			if (criterions != null)
			{
				for (Criterion criterion : criterions)
				{
					if (criterion != null)
					{
						criteria.add(criterion);
					}

				}
			}

			// 获取根据条件分页查询的总行数
			int rowCount = (Integer) criteria.setProjection(
					Projections.rowCount()).uniqueResult();
			criteria.setProjection(null);

			criteria.setFirstResult((pageNo - 1) * pageSize);
			criteria.setMaxResults(pageSize);

			List result = criteria.list();

			pager = new Pager(pageSize, pageNo, rowCount, result);

		} catch (RuntimeException re)
		{
			throw re;
		} finally
		{
			return pager;
		}

	}

Criterion…不定参数传参方式对应BO层代码:
	/**
	 * @function 将传递过来的参数封装成抢修人员Bean,分页查询符合条件的记录
	 * @param pageNo
	 *            当前的页码
	 * @param pageSize
	 *            每页显示的记录数
	 * @param mendName
	 *            抢修人员的名称
	 * @param specialty
	 *            抢修人员的工种
	 * @param post
	 *            抢修人员的职称
	 * @return 将符合条件的记录数以及页码信息封装成PagerBean返回
	 */
	public Pager getInfoByQuery3(int pageNo, int pageSize, String mendName,
			String specialty, String post)
	{
		Criterion criterion1 = null, criterion2 = null, criterion3 = null;
		if (mendName != null && mendName.length() > 0)
		{
			criterion1 = Restrictions.ilike("mendname", mendName,
					MatchMode.ANYWHERE);
		}

		if (specialty != null && specialty.length() > 0)
		{
			criterion2 = Restrictions.ilike("specialty", specialty,
					MatchMode.EXACT);
		}

		if (post != null && post.length() > 0)
		{
			criterion3 = Restrictions.ilike("post", post, MatchMode.EXACT);
		}

		Pager pager = erpManagerDao.findPageByCriteria(pageNo, pageSize,
				criterion1, criterion2, criterion3);

		return pager;
	}

3、HQL检索方式

HQL(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语言有些相识。在Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。
使用Query接口分页查询DAO代码:
	/**
	 * @function 分页显示符合所有的记录数,将查询结果封装为Pager
	 * @param pageNo
	 *            当前页数
	 * @param pageSize
	 *            每页显示的条数
	 * @param instance
	 *            将查询条件封装为专家Bean
	 * @return 查询结果Pager
	 */
	public List<Object> findPageByQuery(int pageNo, int pageSize, String hql,
			Map map)
	{
		List<Object> result = null;
		try
		{
			Query query = this.getSession().createQuery(hql);

			Iterator it = map.keySet().iterator();
			while (it.hasNext())
			{
				Object key = it.next();
				query.setParameter(key.toString(), map.get(key));
			}

			query.setFirstResult((pageNo - 1) * pageSize);
			query.setMaxResults(pageSize);

			result = query.list();

		} catch (RuntimeException re)
		{
			throw re;
		}
		return result;
	}

查询所有记录数的DAO代码:
	/**
	 * @function 根据查询条件查询记录数的个数
	 * @param hql
	 *            hql查询语句
	 * @param map
	 *            用map封装查询条件
	 * @return 数据库中满足查询条件的数据的条数
	 */
	public int getTotalCount(String hql, Map map)
	{
		try
		{
			Query query = this.getSession().createQuery(hql);

			Iterator it = map.keySet().iterator();
			while (it.hasNext())
			{
				Object key = it.next();
				query.setParameter(key.toString(), map.get(key));
			}

			Integer i = (Integer) query.list().get(0);
			return i;
		} catch (RuntimeException re)
		{
			throw re;
		}

	}

BO层代码:
	/**
	 * @function 将传递过来的参数封装成专家Bean,分页查询符合条件的记录
	 * @param pageNo
	 *            当前的页码
	 * @param pageSize
	 *            每页显示的记录数
	 * @param expertName
	 *            专家的名称
	 * @param expertSpecialty
	 *            专家的专业类别
	 * @param post
	 *            专家的行政职位
	 * @return 将符合条件的记录数以及页码信息封装成PagerBean返回
	 */
	public Pager getInfoByQuery(int pageNo, int pageSize, String expertName,
			String expertSpecialty, String post)
	{
		StringBuffer hql = new StringBuffer();
		hql.append("select count(expertid) from EicExpert where 1=1 ");

		Map map = new HashMap();

		if (expertName != null && expertName.length() > 0)
		{
			map.put("expertname", "%" + expertName + "%");
			hql.append("and expertname like :expertname ");
		}
		if (expertSpecialty != null && expertSpecialty.length() > 0)
		{
			map.put("expertspecialty", expertSpecialty);
			hql.append("and expertspecialty like :expertspecialty ");
		}
		if (post != null && post.length() > 0)
		{
			map.put("post", post);
			hql.append("and post like :post ");
		}

		String queryHql = hql.substring(22);
		List result = erpManagerDao.findPageByQuery(pageNo, pageSize,
				queryHql, map);
		int rowCount = erpManagerDao.getTotalCount(hql.toString(), map);

		Pager pager = new Pager(pageSize, pageNo, rowCount, result);
		return pager;
	}


注:Pager类是我封装的一个分页类,包含 每页显示记录数,当前页,总记录数,每页显示数据的集合。因无关紧要,没有贴出来。另外我不知道Query接口有没有类似于Criteria那样可以直接在分页查询记录的同时查询出总记录条数,知道的大虾麻烦告诉下哈。在BO里设置不定参数的时候感觉也不太好,不知道大虾们可有比较好的办法。
分享到:
评论
8 楼 YY008871 2012-07-13  
菜鸟求教。为什么要用map呢??
 Iterator it = map.keySet().iterator();  
        while (it.hasNext())  
        {  
            Object key = it.next();  
            query.setParameter(key.toString(), map.get(key));  
        }  

有什么用吗??
求解?
7 楼 Ayin2767 2012-04-25  
mark 作为资料参考
6 楼 flylovejings 2008-12-31  
mark it 最近也在琢磨Struts+hibernate分页的东西

学习!
5 楼 laiseeme 2008-12-25  
* @param object 
*            将查询条件封装为Object

这个  如果object里面有一对多之类的值是没有效果滴
4 楼 sigon 2008-12-25  
贡喜ls记录已经超过2亿条了,很大的成就啊
3 楼 孤风浪客 2008-12-02  
query.setFirstResult(int arg);
arg的最大值Integer.MAX_VALUE = 2147483647
如果超过这个数你的分页就不行了。
2 楼 hero_2010 2008-12-02  
jjjj8
1 楼 bingqiang 2008-11-19  
同意楼主的技术描述,对使用HQL一次查出总数和分页片段的想法我也追求过,无解……
在此基础上我建议把查询条件封装为一个filter对象由Pager送给DAO,符合条件的结果总数和结果片段封装为一个ResultFragment对象由DAO返回给Pager;拼装Criteria或HQL和解析条件的工作放到DAO中去,Pager中不要涉及Hibernate查询的知识。
感谢楼主的提醒我才发现Query.setParameters(Map)这个好用的方法,以前一直是自己写if一条一条set,惭愧……

相关推荐

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     1.3 小结  1.4 思考题 第2章 Java对象持久化技术概述  2.1 直接通过JDBC API来持久化实体域对象  2.2 ORM简介  2.2.1 对象-关系映射的概念  2.2.2 ORM中间件的基本使用方法  2.2.3 常用的ORM中间件  2.3 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     1.3 小结  1.4 思考题 第2章 Java对象持久化技术概述  2.1 直接通过JDBC API来持久化实体域对象  2.2 ORM简介  2.2.1 对象-关系映射的概念  2.2.2 ORM中间件的基本使用方法  2.2.3 常用的ORM中间件  2.3 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     1.3 小结  1.4 思考题 第2章 Java对象持久化技术概述  2.1 直接通过JDBC API来持久化实体域对象  2.2 ORM简介  2.2.1 对象-关系映射的概念  2.2.2 ORM中间件的基本使用方法  2.2.3 常用的ORM中间件  2.3 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     1.3 小结  1.4 思考题 第2章 Java对象持久化技术概述  2.1 直接通过JDBC API来持久化实体域对象  2.2 ORM简介  2.2.1 对象-关系映射的概念  2.2.2 ORM中间件的基本使用方法  2.2.3 常用的ORM中间件  2.3 ...

    JAVA WEB典型模块与项目实战大全

    1.5 小结  第2章 myedipse开发工具对各种框架的支持  2.1 使用jsp的两种模式  2.2 struts框架的实现  2.3 hibernate框架的实现  2.4 jpa框架的实现  2.5 spring框架的实现  2.6 jsf框架的实现  2.7...

    低清版 大型门户网站是这样炼成的.pdf

    1.5 小结 32 第2章 mvc混血宠儿struts 2 33 2.1 初识mvc新秀struts 2 33 2.1.1 mvc概述 33 .2.1.2 struts 2的mvc实现 35 2.1.3 struts 2的基本组成 36 2.1.4 struts 2的常用类介绍 38 2.1.5 struts 2的业务...

    Grails 技术精解与Web开发实践【源码+样章】----下载不扣分,回帖加1分,欢迎下载,童叟无欺

    11.3 数据库查询小结 143 11.3.1 GORM提供了便捷的 查询方法 143 11.3.2 基于HQL的查询 145 11.4 对GORM进行性能优化 146 11.4.1 设置抓取模式 147 11.4.2 使用二级缓存 147 11.5 使用GRAG工具生成Domain 151 11.6 ...

    《MyEclipse 6 Java 开发中文教程》前10章

    10.5.2.6 使用 HibernateTemplate 实现分页查询 254 10.6 小结 255 10.7 参考资料 255 10.7.1 MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法 255 10.7.2 MyEclipse生成的Spring+Hibernate无法保存数据...

    MyEclipse 6 Java EE 开发中文手册 第九章完整

    第九章 开发Struts 1.x应用 145 9.1 介绍 145 9.2 创建Struts项目 147 9.2.1 创建Web项目 148 9.2.2 ... 175 9.6 小结 176 9.7 参考资料 176 &lt;br&gt;第九章的内容终于完整了,昨天发的那个还不完整

    Spring.3.x企业应用开发实战(完整版).part2

    1.8 小结 第2章 快速入门 2.1 实例功能概述 2.1.1 比Hello World更适用的实例 2.1.2 实例功能简介 2.2 环境准备 2.2.1 创建库表 2.2.2 建立工程 2.2.3 类包及Spring配置文件规划 2.3 持久层 2.3.1 建立领域对象 ...

    Spring3.x企业应用开发实战(完整版) part1

    1.8 小结 第2章 快速入门 2.1 实例功能概述 2.1.1 比Hello World更适用的实例 2.1.2 实例功能简介 2.2 环境准备 2.2.1 创建库表 2.2.2 建立工程 2.2.3 类包及Spring配置文件规划 2.3 持久层 2.3.1 建立领域对象 ...

    Grails权威指南

    第1章 寻找grails之旅  1.1 java的困惑  1.2 webc2.0时代  1.3 java的力量  1.4 什么是grails  1.4.1 与java集成 ... 1.8 本章小结 ....... 2.4 本章小结 ... 3.10 本章小结 ... 11.7 本章小结

    JAVA程序开发大全---上半部分

    1.4 本章小结 5 第2章 MyEclipse集成开发环境的使用 6 2.1 MyEclipse集成开发工具界面 6 2.1.1 MyEclipse的菜单栏 7 2.1.2 MyEclipse的工具栏 13 2.1.3 MyEclipse的透视图 14 2.1.4 MyEclipse的视图 17 2.1.5 ...

    J2EE电子商务系统开发从入门到精通

    1.3 小结..... 7 第2章 Struts基础...... 8 2.1 MVC模式概述..... 8 2.1.1 MVC设计模式..... 8 2.1.2 JSP Model 1与JSP Model 2.. 9 2.2 Struts的体系架构..... 10 2.3 Struts控制器组件类..... 12 2.3.1 Action...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    1.7 本章小结 50 第2章 JSF的基本用法 51 2.1 MVC和JSF 52 2.1.1 MVC和常见MVC框架 52 2.1.2 JSF的优势 56 2.2 下载和安装JSF 57 2.3 JSF使用入门 60 2.3.1 从输入页面开始 60 2.3.2 开发托管Bean 61 2.3.3 定义导航...

    基本于J2EE的Ajax宝典.rar

    本书的写作风格与笔者在新东方的授课风格一致:平实、浅显,放弃新名词,把所有深奥的内容变得浅显易懂。笔者不喜欢罗列一堆的新名词,抄大段大段的理论来炫耀自己。作为一个有多年编程经验的程序员,...19.7 小结 126

    MyEclipse 6 Java 开发中文教程第十章

    241 &lt;br&gt;10.6 小结... 242 &lt;br&gt;10.7 参考资料... 242 &lt;br&gt;10.7.1 MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法... 242 &lt;br&gt;10.7.2 MyEclipse生成的Spring+Hibernate无法保存数据问题的...

Global site tag (gtag.js) - Google Analytics