前段时间在做模糊查询,并利用数据库分页,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> {

public List<Workparam> findRowsByCriteria( DetachedCriteria detachedCriteria, int first, int max);
 
 
 public int findCountByCriteria( DetachedCriteria detachedCriteria);

}

DAO的实现:

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

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

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();
 }
 
 public int getCurrentIndex() {
  return currentIndex;
 }

public void setCurrentIndex(int currentIndex) {
  this.currentIndex = currentIndex<1?1:currentIndex;
 }

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

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

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

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

public void setItems(List<E> items) {
  this.items = items;
 }

public int getPageSize() {
  return pageSize;
 }

public int getFirstIndex() {
  return firstIndex;
 }

public int getTotalCount() {
  return totalCount;
 }

public int getLastIndex() {

return lastIndex;
 }

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

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());
  }
 }
 
 
 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的话,表现形式更加灵活.

Hibernate DetachedCriteria实现的更多相关文章

  1. hibernate DetachedCriteria 分页

    # 具有一个直观的.可扩展的条件查询API是Hibernate的特色. # # 15.1. 创建一个Criteria 实例 # org.hibernate.Criteria接口表示特定持久类的一个查询 ...

  2. Hibernate - DetachedCriteria 的完整用法(转)

    现在对 Hibernate的Criteria 的用法进行总结:     Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Crite ...

  3. hibernate DetachedCriteria实现多表关联查询createAlias的使用

    记录本例查询初衷: 有表: 表1,表2,表3 关系 1 many-to-one 2 2 many-to-one 3 结果:要通过表3中的条件反向查询表1中相关的数据 public Page<We ...

  4. DetachedCriteria详细使用

    一.基本使用 1. 说明 Restrictions 是产生查询条件的工具类. 2. 定义 可以直接用class 创建 DetachedCriteria searDc = DetachedCriteri ...

  5. Hibernate 离线对象构建通用查询

    1.业务场景 当下主系统衍生子业务系统已经成为常态,像京东的物流和金融,阿里的支付宝和淘宝. 子业务系统需要对主系统的资源进行访问,这里的资源我具体化为数据库数据,但日常业务中可能不只是数据. 抽象服 ...

  6. Hibernate的DetachedCriteria使用(含Criteria)

    1.背景了解:Hibernate的三种查询方式 Hibernate总的来说共有三种查询方式:HQL.QBC和SQL三种,这里做简单的概念介绍,不详细进行展开. 1.1 HQL(Hibernate Qu ...

  7. hibernate离线查询DetachedCriteria清除上次的查询条件

    1 原例概述 别名重复问题之后,我们还需要解决的问题就是: 如何清除hibernate的上次查询条件,如果不清除,将会导致上次的查询条件和下次的查询条件合并到了一起. 上次的查询条件和本次的查询条件合 ...

  8. 转:Hibernate中Criteria和DetachedCriteria的完整用法

    原文地址:http://blog.sina.com.cn/s/blog_667528fd0100rkrf.html 设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装.现在对 H ...

  9. Hibernate的DetachedCriteria使用(含Criteria)转载

    https://www.cnblogs.com/deng-cc/p/6428599.html 1.背景了解:Hibernate的三种查询方式 Hibernate总的来说共有三种查询方式:HQL.QBC ...

随机推荐

  1. C#中委托如何使用?(转帖)

    1.委托概述委托是C#中新加入的一个类型,可以把它想作一个和Class类似的一种类型,和使用类相似,使用一个委托时,需要两个步骤,首先你要定义一个委托,就像是定义一个类一样:然后,你可以创建一个或多个 ...

  2. win10激活命令

    以管理员方式打开命令提示符输入以下3条命令slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX 按回车slmgr /skms 54.223.212.31 按回车slmgr ...

  3. Linux系统Centos安装Python3.7

    Linux下默认系统自带python2.7的版本,这个版本被系统很多程序所依赖,所以不建议删除,如果使用最新的Python3那么我们知道编译安装源码包和系统默认包之间是没有任何影响的,所以可以安装py ...

  4. 子网掩码 解释 ---判断各部机器ip 是不是同一个网段

    主要作用是地址判断 编辑 子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据. 最为简单的理解就是两台计算机各自的  IP地址与子网掩码进行AND运算后,如果得出的结果是相同的,  则 ...

  5. linux下给php安装curl、gd(ubuntu)

    安装方法很简单,只需要一条命令. # sudo apt-get install curl libcurl3 libcurl3-dev php5-curl 恭喜,PHP5 cURL安装完毕.记得重启Ap ...

  6. [UE4]动态数组:TArray容器

    为什么使用UE4提供的容器类? 如果你用过C++的STL库,你就知道STL提供了各种各样的容器/数据结构,使得你对处理很多数据的时候非常快捷高效.UE4同样也提供了类似的库,库里面的类型是以T开头的, ...

  7. Mybatis -代码自动生成(generatorConfig.xml)

    参考:http://blog.csdn.net/jinshiyill/article/details/51546676 官方网址: http://www.mybatis.org/generator/c ...

  8. centos自带的dvd中的官方base源,丢失了可以复制下面的内容

    /etc/yum.repos.d/CentOS-Base.repo文件中的内容,同样适用于centos6 [base]name=CentOS-$releasever - Basemirrorlist= ...

  9. 用 tornado 做网站 (7)

    转自:http://wiki.jikexueyuan.com/project/start-learning-python/309.html 用 tornado 做网站 (7) 到上一节结束,其实读者已 ...

  10. JS监听浏览器事件

    Onunload与Onbeforeunload Onunload,onbeforeunload都是在刷新或关闭时调用,可以在<script>脚本中通过window.onunload来指定或 ...