Hibernate分页查询总结

Hibernate分页查询小结

通常使用的Hibernate通常是三种:hql查询,QBC查询和QBE查询:
1、QBE(Qurey By Example)检索方式
QBE是最简单的,但是功能也是最弱的,QBE的功能不是特别强大,仅在某些场合下有用。一个典型的使用场合就是在查询窗口中让用户输入一系列的查询条件,然后返回匹配的对象。QBE只支持=和like比较运算符,无法不大区间值,及其或的匹配。在这种情况下,还是采用HQL检索方式或QBC检索方式。
Java代码 
1./** 
2. * @function 根据传递过来的Object,分页显示在数据库中与其匹配的记录 
3. * @param pageNo 
4. *            当前页数 
5. * @param pageSize 
6. *            每页显示的记录数 
7. * @param object 
8. *            将查询条件封装为Object 
9. * @return 将查询结果封装为Pager返回 
10. */ 
11.public Pager findPageByExample(int pageNo, int pageSize, Object object)  
12.{  
13.    Pager pager = null;  
14.    try 
15.    {  
16.        Criteria criteria = this.getSession().createCriteria(  
17.                Class.forName(this.getEntity()));  
18. 
19.        if (object != null)  
20.        {  
21.            criteria.add(Example.create(object).enableLike());  
22.        }  
23. 
24.        // 获取根据条件分页查询的总行数  
25.        int rowCount = (Integer) criteria.setProjection(  
26.                Projections.rowCount()).uniqueResult();  
27.        criteria.setProjection(null);  
28. 
29.        criteria.setFirstResult((pageNo - 1) * pageSize);  
30.        criteria.setMaxResults(pageSize);  
31. 
32.        List result = criteria.list();  
33. 
34.        pager = new Pager(pageSize, pageNo, rowCount, result);  
35. 
36.    } catch (RuntimeException re)  
37.    {  
38.        throw re;  
39.    } finally 
40.    {  
41.        return pager;  
42.    }  
43. 
44.} 
 /**
  * @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层代码:
Java代码 
1./** 
2. * @function 将传递过来的参数封装成抢修人员Bean,分页查询符合条件的记录 
3. * @param pageNo 
4. *            当前的页码 
5. * @param pageSize 
6. *            每页显示的记录数 
7. * @param mendName 
8. *            抢修人员的名称 
9. * @param specialty 
10. *            抢修人员的工种 
11. * @param post 
12. *            抢修人员的职称 
13. * @return 将符合条件的记录数以及页码信息封装成PagerBean返回 
14. */ 
15.public Pager getInfoByQuery(int pageNo, int pageSize, String mendName,  
16.        String specialty, String post)  
17.{  
18. 
19.    EicMend eicMend = new EicMend();  
20.    if (mendName != null && mendName.length() > 0)  
21.    {  
22.        eicMend.setMendname("%" + mendName + "%");  
23.    }  
24.    if (specialty != null && specialty.length() > 0)  
25.    {  
26.        eicMend.setSpecialty(specialty);  
27.    }  
28.    if (post != null && post.length() > 0)  
29.    {  
30.        eicMend.setPost(post);  
31.    }  
32. 
33.    Pager pager = erpManagerDao  
34.            .findPageByExample(pageNo, pageSize, eicMend);  
35.    return pager;  
36.} 
 /**
  * @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语句如下:
Sql代码 
1.Hibernate: select count(*) as y0_ from YJZX.EIC_MEND this_ where   
2.(this_.MENDNAME like ? and this_.POST like ?)  
3. 
4.Hibernate: select * from ( select this_.MENDID as MENDID23_0_, ......  
5.this_.EXPERTREMARK as EXPERTR28_23_0_ from YJZX.EIC_MEND this_ where   
6.(this_.MENDNAME like ? and this_.POST like ?) ) where rownum <= ? 
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层:
Java代码 
1./** 
2. * @function 分页显示符合所有的记录数,将查询结果封装为Pager 
3. * @param pageNo 
4. *            当前页数 
5. * @param pageSize 
6. *            每页显示的条数 
7. * @param map 
8. *            将查询条件封装为map 
9. * @return 查询结果Pager 
10. */ 
11.public Pager findPageByCriteria(int pageNo, int pageSize, Map map)  
12.{  
13.    Pager pager = null;  
14.    try 
15.    {  
16.        Criteria criteria = this.getSession().createCriteria(  
17.                Class.forName(this.getEntity()));  
18. 
19.        if (map != null)  
20.        {  
21.            Set<String> keys = map.keySet();  
22.            for (String key : keys)  
23.            {  
24.                criteria.add(Restrictions.like(key, map.get(key)));  
25.            }  
26.        }  
27. 
28.        // 获取根据条件分页查询的总行数  
29.        int rowCount = (Integer) criteria.setProjection(  
30.                Projections.rowCount()).uniqueResult();  
31.        criteria.setProjection(null);  
32. 
33.        criteria.setFirstResult((pageNo - 1) * pageSize);  
34.        criteria.setMaxResults(pageSize);  
35. 
36.        List result = criteria.list();  
37. 
38.        pager = new Pager(pageSize, pageNo, rowCount, result);  
39. 
40.    } catch (RuntimeException re)  
41.    {  
42.        throw re;  
43.    } finally 
44.    {  
45.        return pager;  
46.    }  
47. 
48.} 
 /**
  * @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层代码:
Java代码 
1./** 
2. * @function 将传递过来的参数封装成抢修人员Bean,分页查询符合条件的记录 
3. * @param pageNo 
4. *            当前的页码 
5. * @param pageSize 
6. *            每页显示的记录数 
7. * @param mendName 
8. *            抢修人员的名称 
9. * @param specialty 
10. *            抢修人员的工种 
11. * @param post 
12. *            抢修人员的职称 
13. * @return 将符合条件的记录数以及页码信息封装成PagerBean返回 
14. */ 
15.public Pager getInfoByQuery2(int pageNo, int pageSize, String mendName,  
16.        String specialty, String post)  
17.{  
18. 
19.    Map map = new HashMap();  
20. 
21.    if (mendName != null && mendName.length() > 0)  
22.    {  
23.        map.put("mendname", "%" + mendName + "%");  
24.    }  
25.    if (specialty != null && specialty.length() > 0)  
26.    {  
27.        map.put("specialty", specialty);  
28.    }  
29.    if (post != null && post.length() > 0)  
30.    {  
31.        map.put("post", post);  
32.    }  
33. 
34.    Pager pager = erpManagerDao.findPageByCriteria(pageNo, pageSize, map);  
35.    return pager;  
36.} 
 /**
  * @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层代码:
Java代码 
1./** 
2. * @function 分页显示符合所有的记录数,将查询结果封装为Pager 
3. * @param pageNo 
4. *            当前页数 
5. * @param pageSize 
6. *            每页显示的条数 
7. * @param criterions 
8. *            不定参数Criterion 
9. * @return 查询结果Pager 
10. */ 
11.public Pager findPageByCriteria(int pageNo, int pageSize,  
12.        Criterion... criterions)  
13.{  
14.    Pager pager = null;  
15.    try 
16.    {  
17.        Criteria criteria = this.getSession().createCriteria(  
18.                Class.forName(this.getEntity()));  
19.        if (criterions != null)  
20.        {  
21.            for (Criterion criterion : criterions)  
22.            {  
23.                if (criterion != null)  
24.                {  
25.                    criteria.add(criterion);  
26.                }  
27. 
28.            }  
29.        }  
30. 
31.        // 获取根据条件分页查询的总行数  
32.        int rowCount = (Integer) criteria.setProjection(  
33.                Projections.rowCount()).uniqueResult();  
34.        criteria.setProjection(null);  
35. 
36.        criteria.setFirstResult((pageNo - 1) * pageSize);  
37.        criteria.setMaxResults(pageSize);  
38. 
39.        List result = criteria.list();  
40. 
41.        pager = new Pager(pageSize, pageNo, rowCount, result);  
42. 
43.    } catch (RuntimeException re)  
44.    {  
45.        throw re;  
46.    } finally 
47.    {  
48.        return pager;  
49.    }  
50. 
51.} 
 /**
  * @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层代码:
Java代码 
1./** 
2. * @function 将传递过来的参数封装成抢修人员Bean,分页查询符合条件的记录 
3. * @param pageNo 
4. *            当前的页码 
5. * @param pageSize 
6. *            每页显示的记录数 
7. * @param mendName 
8. *            抢修人员的名称 
9. * @param specialty 
10. *            抢修人员的工种 
11. * @param post 
12. *            抢修人员的职称 
13. * @return 将符合条件的记录数以及页码信息封装成PagerBean返回 
14. */ 
15.public Pager getInfoByQuery3(int pageNo, int pageSize, String mendName,  
16.        String specialty, String post)  
17.{  
18.    Criterion criterion1 = null, criterion2 = null, criterion3 = null;  
19.    if (mendName != null && mendName.length() > 0)  
20.    {  
21.        criterion1 = Restrictions.ilike("mendname", mendName,  
22.                MatchMode.ANYWHERE);  
23.    }  
24. 
25.    if (specialty != null && specialty.length() > 0)  
26.    {  
27.        criterion2 = Restrictions.ilike("specialty", specialty,  
28.                MatchMode.EXACT);  
29.    }  
30. 
31.    if (post != null && post.length() > 0)  
32.    {  
33.        criterion3 = Restrictions.ilike("post", post, MatchMode.EXACT);  
34.    }  
35. 
36.    Pager pager = erpManagerDao.findPageByCriteria(pageNo, pageSize,  
37.            criterion1, criterion2, criterion3);  
38. 
39.    return pager;  
40.} 
 /**
  * @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代码:
Java代码 
1./** 
2. * @function 分页显示符合所有的记录数,将查询结果封装为Pager 
3. * @param pageNo 
4. *            当前页数 
5. * @param pageSize 
6. *            每页显示的条数 
7. * @param instance 
8. *            将查询条件封装为专家Bean 
9. * @return 查询结果Pager 
10. */ 
11.public List<Object> findPageByQuery(int pageNo, int pageSize, String hql,  
12.        Map map)  
13.{  
14.    List<Object> result = null;  
15.    try 
16.    {  
17.        Query query = this.getSession().createQuery(hql);  
18. 
19.        Iterator it = map.keySet().iterator();  
20.        while (it.hasNext())  
21.        {  
22.            Object key = it.next();  
23.            query.setParameter(key.toString(), map.get(key));  
24.        }  
25. 
26.        query.setFirstResult((pageNo - 1) * pageSize);  
27.        query.setMaxResults(pageSize);  
28. 
29.        result = query.list();  
30. 
31.    } catch (RuntimeException re)  
32.    {  
33.        throw re;  
34.    }  
35.    return result;  
36.} 
 /**
  * @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代码:
Java代码 
1./** 
2. * @function 根据查询条件查询记录数的个数 
3. * @param hql 
4. *            hql查询语句 
5. * @param map 
6. *            用map封装查询条件 
7. * @return 数据库中满足查询条件的数据的条数 
8. */ 
9.public int getTotalCount(String hql, Map map)  
10.{  
11.    try 
12.    {  
13.        Query query = this.getSession().createQuery(hql);  
14. 
15.        Iterator it = map.keySet().iterator();  
16.        while (it.hasNext())  
17.        {  
18.            Object key = it.next();  
19.            query.setParameter(key.toString(), map.get(key));  
20.        }  
21. 
22.        Integer i = (Integer) query.list().get(0);  
23.        return i;  
24.    } catch (RuntimeException re)  
25.    {  
26.        throw re;  
27.    }  
28. 
29.} 
 /**
  * @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层代码:
Java代码 
1./** 
2. * @function 将传递过来的参数封装成专家Bean,分页查询符合条件的记录 
3. * @param pageNo 
4. *            当前的页码 
5. * @param pageSize 
6. *            每页显示的记录数 
7. * @param expertName 
8. *            专家的名称 
9. * @param expertSpecialty 
10. *            专家的专业类别 
11. * @param post 
12. *            专家的行政职位 
13. * @return 将符合条件的记录数以及页码信息封装成PagerBean返回 
14. */ 
15.public Pager getInfoByQuery(int pageNo, int pageSize, String expertName,  
16.        String expertSpecialty, String post)  
17.{  
18.    StringBuffer hql = new StringBuffer();  
19.    hql.append("select count(expertid) from EicExpert where 1=1 ");  
20. 
21.    Map map = new HashMap();  
22. 
23.    if (expertName != null && expertName.length() > 0)  
24.    {  
25.        map.put("expertname", "%" + expertName + "%");  
26.        hql.append("and expertname like :expertname ");  
27.    }  
28.    if (expertSpecialty != null && expertSpecialty.length() > 0)  
29.    {  
30.        map.put("expertspecialty", expertSpecialty);  
31.        hql.append("and expertspecialty like :expertspecialty ");  
32.    }  
33.    if (post != null && post.length() > 0)  
34.    {  
35.        map.put("post", post);  
36.        hql.append("and post like :post ");  
37.    }  
38. 
39.    String queryHql = hql.substring(22);  
40.    List result = erpManagerDao.findPageByQuery(pageNo, pageSize,  
41.            queryHql, map);  
42.    int rowCount = erpManagerDao.getTotalCount(hql.toString(), map);  
43. 
44.    Pager pager = new Pager(pageSize, pageNo, rowCount, result);  
45.    return pager;  
46.} 
 /**
  * @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里设置不定参数的时候感觉也不太好,不知道大虾们可有比较好的办法。