`
heaven.robin
  • 浏览: 30193 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

利用DetachedCriteria实现模糊查询和分页

阅读更多
 前段时间在做模糊查询,并利用数据库分页,DAO用hibernate实现,刚开始的时候
根据业务层的数据,拼hql语句进行查询,且不说要进行一些if判断,单从结构上来说,
底层的数据访问层依赖于业务层或者表现层了.
  比如说,我想查询姓王的员工,年龄大于30岁的,在DAO显然要name like '%王' and age >30,如果业务发生变化,查询与王**姓名相同,年龄等于30的,那就改hql语句吧,
name ='王**' and age =30,数据访问层依赖于业务层,觉得不合理.
 Hibernate3提供一个新的东西,DetachedCriteria可以脱离session分离查询条件,也就是把查询条件通过业务层或表现层传入,数据访问层进行数据操作,解决了数据访问层依赖于业务层的问题.
实现细节:
结合泛型设计DAO

public interface DAO<PO,ID extends java.io.Serializable> {

/**
  * find rows by detachedCriteria
  */
 public List<Workparam> findRowsByCriteria( DetachedCriteria detachedCriteria, int first, int max);
 
 /**
  * find count by detachedCriteria
  */
 public int findCountByCriteria( DetachedCriteria detachedCriteria);

}

DAO的实现:

public class DAOHibernate<PO,ID extends java.io.Serializable> extends HibernateDaoSupport implements DAO<PO,ID> {

 /**
  * find workparma objects by detachedCriteria
  */
 @SuppressWarnings("unchecked")
 public List<PO> findRowsByCriteria(DetachedCriteria detachedCriteria, int first, int max) {
  // TODO 自动生成方法存根
  return getHibernateTemplate().findByCriteria(detachedCriteria, first, max);

 

 /**
  * find totalCount by detachedCriteria
  */
 public int findCountByCriteria(DetachedCriteria detachedCriteria) {
  // TODO 自动生成方法存根
  detachedCriteria.setProjection(Projections.rowCount());
  System.out.println(getHibernateTemplate().findByCriteria(detachedCriteria));
  return (Integer) getHibernateTemplate().findByCriteria(detachedCriteria).get(0);
 }


 }

 

}

具体实现的DAO:

public interface WorkparamDAO extends DAO<Workparam,Integer>{

}

implements:

public class WorkparamDAOHibernate extends DAOHibernate<Workparam,Integer> implements WorkparamDAO {

}

 
在利用spring管理DAOHibernate的时候,最好设置其abstract="true",即为抽象的,
实际上DAOHibernate在没有由子类参数化PO,ID类型之前,也是不能使用的.它也不知道PO,ID是什么类型,编译时不会报错,但运行的时候就会出错.
 
接下来做一个分页工具类,封装分页信息:

public class PageSplitUtil<E> {
 
 //存放记录集合
 private List<E> items;
 
 //每页记录数
 private int pageSize = Constants.PAGE_SIZE;
 
 //总记录数
 //初始化其值,为了判断缓存
 private int totalCount=-1;
 
 //分页索引数组
 private int indexs[];
 
 //开始索引值
 private int firstIndex = Constants.FIRST_INDEX;
 
 //当前页索引
 private int currentIndex;
 
 //是否有上一个索引
 private boolean hasPreIndex;
 
 //是否有下一个索引
 private boolean hasNextIndex;
 
 //上一页索引
 private int preIndex;
 
 //上一页索引
 private int nextIndex;
 
 //最后一页
 private int lastIndex;
 
 //小分页数
 private int splitCount=Constants.SPLIT_COUNT;
 
 //存放url
 private String action;

 //constructor
 public PageSplitUtil(List<E> items,int current,int totalCount){
  this.items = items;
  this.totalCount = totalCount ;
  this.currentIndex = current;
  calculateTotalPage();
 }
 
 
 public PageSplitUtil(List<E> items,int current,int pageSize,int totalCount){
  this.items = items;
  this.pageSize = pageSize;
  this.totalCount = totalCount;
  this.currentIndex = current;
  calculateTotalPage();
 }
 /**
  * @return currentIndex
  */
 public int getCurrentIndex() {
  return currentIndex;
 }

 /**
  * @param currentIndex 要设置的 currentIndex
  */
 public void setCurrentIndex(int currentIndex) {
  this.currentIndex = currentIndex<1?1:currentIndex;
 }

 /**
  * @return hasNextIndex
  */
 public boolean isHasNextIndex() {
  return currentIndex>=lastIndex || lastIndex ==1 ?false:true;
 }

 /**
  * @return hasPreIndex
  */
 public boolean isHasPreIndex() {
  return currentIndex<=firstIndex ?false:true;
 }

 /**
  * @return indexs
  */
 public int[] getIndexs() {
  indexs = new int[lastIndex];
  for (int i = 0; i < lastIndex; i++) {
   indexs[i]=i+1;
  }
  return indexs;
 }

 /**
  * @return items
  */
 public List<E> getItems() {
  return items;
 }

 /**
  * @param items 要设置的 items
  */
 public void setItems(List<E> items) {
  this.items = items;
 }

 /**
  * @return pageSize
  */
 public int getPageSize() {
  return pageSize;
 }


 /**
  * @return firstIndex
  */
 public int getFirstIndex() {
  return firstIndex;
 }


 /**
  * @return totalCount
  */
 public int getTotalCount() {
  return totalCount;
 }


 /**
  * @return lastIndex
  */
 public int getLastIndex() {

  return lastIndex;
 }

 /**
  * @return splitCount
  */
 public int getSplitCount() {
  return splitCount;
 }
 /**
  * @return nextIndex
  */
 public int getNextIndex() {
  return currentIndex>=lastIndex ? lastIndex : currentIndex+1;
 }

 /**
  * @return preIndex
  */
 public int getPreIndex() {
  return currentIndex<=firstIndex ? firstIndex : currentIndex-1;
 } 
 
 
 public String getAction() {
  return action;
 }

 public void setAction(String action) {
  this.action = action;
 }


 //计算总页数
 private void calculateTotalPage(){
  if(totalCount>0){
   lastIndex=(int) Math.ceil((double)totalCount/pageSize);

  }else{
   lastIndex =0;
  }
 }

}

 
把detachedCriteria查询条件在业务层实现

public PageSplitUtil findRowsByCriteria(Workparam param,int current,int pageSize) {
  // TODO 自动生成方法存根
  DetachedCriteria dc = DetachedCriteria.forClass(param.getClass());
  dc.add(Restrictions.like("workName", param.getWorkName(), MatchMode.ANYWHERE));
   dc.add(Restrictions.eq("workState", param.getWorkState())).addOrder(Order.desc("workId"));

  int totalCount=workparamDAO.findCountByCriteria(dc);
  
  PageSplitUtil ps=new PageSplitUtil<Workparam>(list,current,pageSize,totalCount);
  return ps;
 }

由于detachedCriteria是根据Criteria的扩展实现,Critetia利用Express来封装了判断的条件以及sql函数(count(),avg()等).在hibernate3中,利用Restrictions封装逻辑判断条件,如like,eq,between等,用Projections封装了sql函数,如count(),avg()等.
MatchMode为匹配方式:START,前边匹配,END,后边匹配,ANYWHERE前后匹配,EXACT完全匹配四种方式.
detachedCriteria支持数据库查询时的排序,addOrder(Order.asc("按属性排序"));
detachedCriteria的多表关联查询,dc.createAlias("workType", "t").add(Restrictions.like("t.typeName", "早班类"));workType作为Workparam的关联属性,在映射文件中会根据其关系对相关联的表进行模糊查询.
 
为了方便在每个页面使用,用自定义标签显示分页信息:

public class PageSplitTag extends BodyTagSupport {
 private static final long serialVersionUID = -1411548776656848362L;

 private String action="";

 private PageSplitUtil pageUtil;
 
 public PageSplitTag() {
  // TODO 自动生成构造函数存根
 }
 
 public int doStartTag() throws JspException{
  try {
   String txt=getText().toString();
   pageContext.getOut().write(txt);
   return this.SKIP_BODY;
  } catch (IOException e) {
   // TODO 自动生成 catch 块
   throw new JspException("输出错误"+e.getMessage());
  }
 }
 
 /**
  * 输出文本
  * @return
  */
 private StringBuffer getText() {
  // TODO 自动生成方法存根
  if(pageUtil==null) return new StringBuffer("初始化分页失败");
  
  //判断action是否设置
  if(action==null||"".equals(action)){
   action=pageUtil.getAction();
  }
  
  StringBuffer txt=new StringBuffer("<form action="+action+" method=\"get\" name=\"splitfrm\">");
  txt.append("<td height=\"27\" align=\"center\">共有<font color=\"red\">"
     +pageUtil.getTotalCount()+"</font>条记录&nbsp;&nbsp;");
  txt.append("<font color=\"red\">"+pageUtil.getPageSize()+"</font>条/页&nbsp;&nbsp;");
  //判断是否有上一页
  if(pageUtil.isHasPreIndex()){
   txt.append("<a href="+action+"?page="+pageUtil.getFirstIndex()+">首页</a>&nbsp;");
   txt.append("<a href="+action+"?page="+pageUtil.getPreIndex()+">&lt;&lt;&lt;</a>&nbsp;&nbsp;");
  }
  else{
   txt.append("<font color=\"#999966\">首页</font>&nbsp;");
   txt.append("<font color=\"#999966\">&lt;&lt;&lt;</font>&nbsp;");
  }
  //小的分页
  int indexs[]=pageUtil.getIndexs();
  int currentIndex=pageUtil.getCurrentIndex();
  int splitCount=pageUtil.getSplitCount();
  int count=0;
  //每次显示从当前页开始的后splitCount页
  if(pageUtil.getLastIndex()-(currentIndex+splitCount)>=0){
   count=currentIndex+splitCount;
  }else{
   count=indexs.length;
  }
   for (int i = currentIndex-1; i < count; i++) {
     if(currentIndex == indexs[i] ){
      txt.append("<font color=\"red\">"+currentIndex+"</font>&nbsp;");
     }else{
      txt.append("<a href="+action+"?page="+indexs[i]+">"+indexs[i]+"</a>&nbsp;");
    }
   }
  txt.append("&nbsp");
  
  //判断是否还有下一页
  if(pageUtil.isHasNextIndex()){
   txt.append("<a href="+action+"?page="+pageUtil.getNextIndex()+">&gt;&gt;&gt;</a>&nbsp;");
   txt.append("<a href="+action+"?page="+pageUtil.getLastIndex()+">尾页</a>&nbsp;");
  }
  else{
   txt.append("<font color=\"#999966\">&gt;&gt;&gt;</font>&nbsp;");
   txt.append("<font color=\"#999966\">尾页</font>&nbsp;");
  }
  //页数选择
  txt.append("GO<select name=\"page\" onchange=\"javascript:document.splitfrm.submit();\">");
  for (int i = 0; i < indexs.length; i++) {
   if(currentIndex == indexs[i]){
    txt.append("<option value="+indexs[i]+" selected=\"selected\">"+indexs[i]+"</option>");
   }else{
    txt.append("<option value="+indexs[i]+">"+indexs[i]+"</option>");
   }
  }
  txt.append("</select>页</form></td>");
  return txt;
 }

 

setter..

}

然后在每个页面用自定义标签就可以了:

<%@ taglib uri="http://www.oamanager.com/mytag" prefix="tag"%>

<tag:splitPage action="${splitList.action}" pageUtil="${splitList}"></tag:splitPage>

 设置action请求的路径和分页信息就可以了.
 
缺点:
1:在DAO接口的设计中依赖于hibernate的实现.如果改用ibatis或ojb,需更改接口,不符合接口的设计原则.
2:分页的自定义Tag显示形式固定,如果利用DIV+CSS,或者XML+CSS的话,表现形式更加灵活.
      
  thanks
分享到:
评论

相关推荐

    DetachedCriteria查询

    DetachedCriteria 查询 DetachedCriteria 是 Hibernate 中的一种离线查询对象,它可以在不依赖 Session 的情况下生成动态 SQL 语句并进行查询。下面是 DetachedCriteria 查询的详细知识点: 创建 DetachedCriteria...

    springMVC+hibernate的条件查询加分页的demo

    总的来说,"springMVC+hibernate的条件查询加分页的demo"涵盖了Web应用中常见的查询和分页需求,通过SpringMVC接收和处理用户请求,利用Hibernate的Criteria查询动态构造SQL,并通过设置分页参数实现数据的分批次...

    Hibernate 使用DetachedCriteria操作

    - 在服务层进行分页查询时,可以先创建DetachedCriteria,然后在视图层根据请求参数调整限制条件,避免重复计算。 **4. DetachedCriteria 的基本用法** 创建DetachedCriteria通常从`DetachedCriteria.forClass()`...

    Nhibernate的模糊查询

    全模糊查询(如`'%关键词%'`)很难利用到索引,应尽量避免。如果必须使用,考虑使用全文搜索引擎如Lucene.NET或SOLR与Nhibernate集成。 3. **分页查询** 对于大数据量的模糊查询,记得使用分页,避免一次性加载...

    DetachedCriteria笔记

    DetachedCriteria

    Hibernate - DetachedCriteria 的完整用法

    Hibernate 的 Criteria 和 DetachedCriteria 是两个不同的概念,虽然它们都是用于查询数据的,但它们在创建和使用上有所不同。 首先,Criteria 是在线的,需要通过 Hibernate Session 来创建,即使用 `session....

    struts2+spring+hibernate分页查询

    Struts2、Spring和Hibernate是Java Web开发中的三大框架,它们各自负责不同的职责:Struts2主要用于MVC...在实际项目中,需要根据具体需求和业务场景,选择合适的分页策略和实现方式,同时注意性能优化和安全防护。

    DetachedCriteria使用介绍

    // 主查询和子查询关联 (也就是 where unid in (select usernuid from)) searDc.add(Property.forName("unid").in(sub)); ``` 这样,你就可以构建类似于 SQL 的子查询结构:`Select * from Person a where a.unid ...

    Hibernate(24): 为什么用DetachedCriteria不能表连接地取数据?

    在Java的持久化框架Hibernate中,DetachedCriteria是一个强大的查询工具,它允许我们在不与Session交互的情况下构建查询条件。然而,DetachedCriteria在处理复杂的关联查询,尤其是涉及到表连接(JOIN)时,可能存在...

    浅谈DetachedCriteria和Criteria的使用方法(必看)

    这样,查询语句的构造完全被搬离到Web层实现,而业务层则只负责完成持久化和查询的封装。 Criteria的使用方法: Criteria是在线的查询工具,由Hibernate Session进行创建。Criteria可以用于动态生成SQL语句,进行...

    DetachedCriteria Criteria 使用方法

    它允许在Web层构造查询条件,并将其作为参数传递给业务层对象,从而实现查询语句构造的完全解耦。这样,业务层仅需关注数据的持久化和查询封装,而不必关心具体的查询条件构建细节。 #### 二、`DetachedCriteria` ...

    Hibernate+sqlserver2000分页

    在Hibernate中实现分页,主要涉及两个关键概念:`Criteria API` 和 `Pagination`。`Criteria API` 是一种更加灵活和类型安全的查询方式,可以替代传统的HQL(Hibernate Query Language)来构建动态查询。而`...

    Hibernate 在查询操作中要使用分页+命名参数+排序技术

    在IT行业中,数据库查询是日常开发中的重要环节,特别是在大型应用中,为了提高用户体验和系统性能,分页、命名参数和排序技术的应用至关重要。本文将深入探讨如何在使用Hibernate框架时,有效地结合这些技术进行...

    sh分页,增删改查

    Criteria查询提供了动态构建查询的方式,可以通过DetachedCriteria实现分页;HQL是面向对象的查询语言,可以方便地进行分页;对于更复杂的SQL操作,可以直接使用SQL查询,并配合 ScrollableResults 接口实现分页。在...

    Hibernate中,利用Criteria查询容器实现sql的写法

    本篇将详细讲解如何在Hibernate中利用Criteria查询来实现类似SQL的查询操作,并探讨其在实际开发中的应用。 Criteria查询是Hibernate提供的一种灵活的查询方式,它可以让我们根据业务需求动态地构建查询条件。这种...

    QBC的各种查询

    Criteria接口提供了多种方法,如add()用于添加查询条件,setFirstResult()和setMaxResults()用于分页,createAlias()用于关联查询等。DetachedCriteria则允许我们在不直接影响Session的情况下构建查询,提高了代码的...

    六种方式实现hibernate查询

    六种方式实现Hibernate查询 Hibernate是一个功能强大的持久层框架,它提供了多种方式来查询数据库。下面我们将详细介绍六种方式实现Hibernate查询。 HQL查询 HQL(Hibernate Query Language)是Hibernate自己的...

    hibernate查询详解

    DetachedCriteria允许在不与数据库交互的情况下构建查询,适用于延迟加载和构建复杂查询。 5. 例子查询: 基于对象实例进行查询,适用于查找与给定实例相似的对象。 6. 命名查询: 将HQL或SQL查询声明在配置...

    Hibernate中查询的法方

    为了解决这个问题,可以在`DetachedCriteria`中设置相应的查询条件,以实现带条件的分页查询。 通过理解和熟练运用这些基本查询方法,你可以有效地利用Hibernate进行数据操作,从而提高开发效率。在实际项目中,还...

    Hibernate 查询经典练习题

    在本文中,我们将探讨基于Hibernate的查询实践,包括HQL(Hibernate Query Language)和Criteria API的使用。我们将通过两个经典的练习题来深入理解这两个查询方式,并讨论它们在处理不同查询需求时的特点。 ### ...

Global site tag (gtag.js) - Google Analytics