前段时间在做模糊查询,并利用数据库分页,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>条记录 "); txt.append("<font color=\"red\">"+pageUtil.getPageSize()+"</font>条/页 "); //判断是否有上一页 if(pageUtil.isHasPreIndex()){ txt.append("<a href="+action+"?page="+pageUtil.getFirstIndex()+">首页</a> "); txt.append("<a href="+action+"?page="+pageUtil.getPreIndex()+"><<<</a> "); } else{ txt.append("<font color=\"#999966\">首页</font> "); txt.append("<font color=\"#999966\"><<<</font> "); } //小的分页 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> "); }else{ txt.append("<a href="+action+"?page="+indexs[i]+">"+indexs[i]+"</a> "); } } txt.append(" "); //判断是否还有下一页 if(pageUtil.isHasNextIndex()){ txt.append("<a href="+action+"?page="+pageUtil.getNextIndex()+">>>></a> "); txt.append("<a href="+action+"?page="+pageUtil.getLastIndex()+">尾页</a> "); } else{ txt.append("<font color=\"#999966\">>>></font> "); txt.append("<font color=\"#999966\">尾页</font> "); } //页数选择 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 分页
# 具有一个直观的.可扩展的条件查询API是Hibernate的特色. # # 15.1. 创建一个Criteria 实例 # org.hibernate.Criteria接口表示特定持久类的一个查询 ...
- Hibernate - DetachedCriteria 的完整用法(转)
现在对 Hibernate的Criteria 的用法进行总结: Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Crite ...
- hibernate DetachedCriteria实现多表关联查询createAlias的使用
记录本例查询初衷: 有表: 表1,表2,表3 关系 1 many-to-one 2 2 many-to-one 3 结果:要通过表3中的条件反向查询表1中相关的数据 public Page<We ...
- DetachedCriteria详细使用
一.基本使用 1. 说明 Restrictions 是产生查询条件的工具类. 2. 定义 可以直接用class 创建 DetachedCriteria searDc = DetachedCriteri ...
- Hibernate 离线对象构建通用查询
1.业务场景 当下主系统衍生子业务系统已经成为常态,像京东的物流和金融,阿里的支付宝和淘宝. 子业务系统需要对主系统的资源进行访问,这里的资源我具体化为数据库数据,但日常业务中可能不只是数据. 抽象服 ...
- Hibernate的DetachedCriteria使用(含Criteria)
1.背景了解:Hibernate的三种查询方式 Hibernate总的来说共有三种查询方式:HQL.QBC和SQL三种,这里做简单的概念介绍,不详细进行展开. 1.1 HQL(Hibernate Qu ...
- hibernate离线查询DetachedCriteria清除上次的查询条件
1 原例概述 别名重复问题之后,我们还需要解决的问题就是: 如何清除hibernate的上次查询条件,如果不清除,将会导致上次的查询条件和下次的查询条件合并到了一起. 上次的查询条件和本次的查询条件合 ...
- 转:Hibernate中Criteria和DetachedCriteria的完整用法
原文地址:http://blog.sina.com.cn/s/blog_667528fd0100rkrf.html 设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装.现在对 H ...
- Hibernate的DetachedCriteria使用(含Criteria)转载
https://www.cnblogs.com/deng-cc/p/6428599.html 1.背景了解:Hibernate的三种查询方式 Hibernate总的来说共有三种查询方式:HQL.QBC ...
随机推荐
- PHP查找中文字符的解决方案
在PHP中查找中文字符,有两种方案.1.中文字符是gbk(gb2312)有两种解决方法第一种:将PHP保存为ASCII编码,然后使用strpos查找,如:strpos($curl_res, ‘哈哈’) ...
- 深入理解ASP.NET MVC(2)
系列目录 请求是如何进入MVC框架的(inbound) 当一个URL请求到来时,系统调用一个注册的IHttpModules:UrlRoutingModule,它将完成如下工作: 一.在RouteTab ...
- java学习之路之javaSE基础2
java学习之路之javaSE基础2 所有的代码都是引用他人写的. 1.逻辑运算符 //&,|,^,! //int x = 10; //5 < x < 15 //x > 5 ...
- 子网掩码 解释 ---判断各部机器ip 是不是同一个网段
主要作用是地址判断 编辑 子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据. 最为简单的理解就是两台计算机各自的 IP地址与子网掩码进行AND运算后,如果得出的结果是相同的, 则 ...
- http 各个状态返回值
code 定义在 org.apache.http.HttpStatus 转载来自于:http://desert3.iteye.com/blog/1136548 502 Bad Gateway:tomc ...
- [UE4]蓝图Get Control Rotation获取人物角色朝向,设置默认人物相机,朝向与controller绑定
具体应用:控制人物移动方向 也可以使用“CombineRotators”将角色控制器Z轴旋转90°,然后再取正面方向,达到跟“Get Right Vector”一样的效果: 设置关联人物朝向使用控制器 ...
- sklearn中的metrics模块中的Classification metrics
metrics是sklearn用来做模型评估的重要模块,提供了各种评估度量,现在自己整理如下: 一.通用的用法:Common cases: predefined values 1.1 sklearn官 ...
- SQL中select与set的区别
转自 : http://www.cnblogs.com/4mylife/archive/2012/10/25/2738466.html 下表列出 SET 与 SELECT 的区别 SELECT S ...
- Vector的小知识点
预留容量的两类方式: 1.不调用默认的构造函数 vector<int> v; v.push_back(111); v.reserve(20); std::copy(v.begin(), v ...
- WCF服务部署
一.将WCF服务部署到IIS上 1.首先检测电脑上是否安装了IIS,一般来说Win7以上系统自带IIS 2.下面进行IIS服务的开启设置 控制面板=>打开或关闭Windos功能 3.勾选该窗口中 ...