`
gaogengzhi
  • 浏览: 107066 次
  • 性别: 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,惭愧……

相关推荐

    在JDBC,hibernate中实现分页

    #### 小结 以上代码展示了如何在Hibernate和JDBC中实现数据分页。通过Hibernate提供的API可以方便快捷地实现分页功能,而JDBC则需要更多的手动处理来构建合适的SQL语句和处理结果集。两种方法各有优势,开发者可以...

    hibernate小结

    HibernateUtil通常包含对数据库的增删改查操作,如增加、删除、更新、查询单个对象、查询所有对象和分页查询。在进行写操作时,需要开启事务,并在操作完成后提交或回滚。 【Hibernate对象的三种状态】 1. 瞬态...

    Hibernate实体查询(ceriteria)精解

    ### 小结 通过上述内容可以看出,Criteria 查询方式为 Hibernate 提供了一个灵活且强大的查询机制。它可以方便地构建各种复杂的查询条件,并且支持排序、分页等高级功能,同时还能处理关联查询。对于那些希望避免...

    精通 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的检索方式

    ### 小结 以上介绍了Hibernate的五种检索方式:导航对象图检索、OID检索、HQL检索、QBC检索以及本地SQL检索。每种检索方式都有其独特的应用场景和特点。在实际开发过程中,根据项目的需求和技术背景选择合适的检索...

    精通 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 ...

    hibernate初级教程图解

    #### 四、小结 本篇教程通过图解的形式介绍了Hibernate的基础概念及其核心接口的功能和使用方法。通过学习这些内容,开发者可以更好地理解Hibernate的工作原理,并能够在实际开发中有效地利用这些接口来提高开发效率...

    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...

    Hibernate 经常用的一些HQL语句

    ### 小结 HQL提供了丰富的查询语法,能够满足复杂的数据查询需求。通过上述实例,我们可以看到HQL不仅支持基本的CRUD操作,还支持更高级的功能,如模糊查询、参数绑定、聚合函数、分页以及多表关联等。掌握这些技巧...

    J2EE电子商务系统开发从入门到精通:基于Struts和Hibernate技术实现

    - **分页显示的实现**:通过SQL查询或Hibernate API实现数据分页。 #### 企业在线信息系统网站概述与架构设计 - **概述**: - 该网站旨在为企业的日常运营提供一个综合的信息管理系统。 - 包括员工登录、人事...

    J2EE电子商务系统开发从入门到精通基于Struts和Hibernate技术实现

    - 介绍了如何在Hibernate中实现分页查询功能。 - **3.9 小结** - 总结了学习Hibernate的基本要点。 #### 企业在线信息系统网站概述与架构设计 - **4.1 企业在线综合信息管理网站概述** - 描述了企业在线综合...

    J2EE电子商务系统开发从入门到精通--基于Struts和Hibernate技术实现

    **1.3 小结** - J2EE为企业级应用提供了一套完整的解决方案,能够有效解决分布式计算环境下的复杂问题。 #### Struts基础 **2.1 MVC模式概述** - **2.1.1 MVC设计模式** - MVC(Model-View-Controller)设计模式...

Global site tag (gtag.js) - Google Analytics