简化NHibernate查询并分页

最近公司在做一款OA的二次开发,是基于 J2EE 架构的 采用的 Spirng3 +Struts2+Hibernate3 UI 采用的EXTJS3。这款产品的框架设计的比较好,这几天正在研究。其中hibernate查询采用的通用方法,进行集中的查询字段收集、创建Criteria、查询数据。
首先介绍一下实现思路。
定义一个QueryFilter对象,然后在构造中接受一个HttpServletRequest对象,QueryFilter对HttpServletRequest中的 查询参数进行遍历,找到符合约定的参数时,对参数进行分析,并封装成hibernate的criteria对象,再交给service,service再交给dao,进由hibernate进行数据查询。
以下是大致的方法签名和调用
QueryFilter filter = new QueryFilter(HttpServletRequest request); List list = bookTypeService.getAll(filter);
过滤条件的名称必须符合如下规则:Q_firstName_S_EQ ,其中Q标识该查询参数是一个QueryFilter能识别的字符,firstName 表示待查询的属性名称(可以是外键对象的属性),S 表示为 String 类型,EQ 表示 equals ,当然 S 位置 和 EQ 位置还有其它约定的表达式。通过这种方式,在进行数据查询时,不需要进行硬编码,只需要在html代码,或者JavaScript进行 Ajax 查询时,指定符合要求的querystring 即可。
以下是extjs中查询时候的代码
return new Ext.Panel({ id : 'BookTypeView', title : '档案类别列表', iconCls : 'menu-book-type', autoScroll : true, items : [new Ext.FormPanel({ height : 35, frame : true, id : 'BookTypeSearchForm', layout : 'column', defaults : { xtype : 'label' }, items : [{ text : '请输入查询条件:' }, { text : '档案类别' }, { xtype : 'textfield', name : 'Q_typeName_S_LK' }, { xtype : 'button', text : '查询', iconCls : 'search', handler : function() { search(); } }, { xtype : 'button', text : '取消查询条件', iconCls : 'btn-del', handler : function() { var searchPanel = Ext.getCmp('BookTypeSearchForm'); var grid = Ext.getCmp('BookTypeGrid'); searchPanel.items.get(2).setValue(""); search(); } }] }), this.setup()] }); };
为了使我以后更懒的工作,周末花了点时间写了一个C#&Asp.Net的实现(其实我主要是做.NET平台的,Java我真的不想做)。大致上还是采用的这款OA中实现的思路。但是发现一个问题,它的QueryFilter只能够进行与查询,也就是各个查询条件是用AND相连接的,无法进行OR查询,或者 多个条件单独与或 在 与 另外一个条件与或 , 比如 (a = 1 and b = 2) or c = false ,所以我简单实现了 多组查询的功能。查询字符串的约定规则模仿Q_firstName_S_EQ 稍微做了一些改变 ,例如:Q_firstName_S_EQ_AND_0_1 , 其中 Q_firstName_S_EQ 部分是完全一致的。
AND 为条件聚合方式,可以是 AND 或者 OR ,
0 必须为数字,表示查询条件的组 , 相同的组ID将被归并成一个查询条件
1 必须为数字,表示查询条件组中成员的顺序
查询条件组 与 组成员都将按照顺序产生 HQL 语句。
可能光从字面上理解有点误会,笔者表达的也却有欠缺。
打个比方:
Q_firstName_S_LK_AND_0_1,
Q_lastName_S_LK_OR_0_2,
Q_age_I_>_AND_1_1,
其中 Q_firstName_S_LK_AND_0_1,Q_lastName_S_LK_OR_0_2 属于同一组 将产生 (firstName like :firstName and lastName like :firstName )
Q_age_I_>_AND_1_1 单独一组 将产生 (age = :age)
两组合并为一句HQL语句为(firstName like :firstName and lastName like :firstName) or (age = :age) 。
那么 and 和 or 又是按照什么规则连续的呢?
组我的规则是,同一组的查询条件的聚合类型作用于下一个查询条件,前一组的最后一个成员的聚合方式作用于下一组,又很拗口…………
对照一下
(firstName like :firstName and lastName like :firstName) or (age = :age) 。
Q_firstName_S_LK_AND_0_1,Q_lastName_S_LK_OR_0_2,Q_age_I_>_AND_1_1 ,??? 最后一个AND 呢?只要当前查询条件是最后一个,AND 或者 OR 将被忽略。很难设计啊…
以下是创建HQL的部分C#代码
//-----------------动态创建 where 语句开始-------------------- string lastCT = ""; var lastGroup = queryable.LastOrDefault(); foreach (var item in queryable) { var last = item.LastOrDefault(); hqlSb.Append(" ("); foreach (var _item in item) { lastCT = _item.ConnectionType; hqlSb.Append(" t."); hqlSb.Append(_item.CreateHqlPart()); if (!last.Equals(_item)) { hqlSb.Append(" " + lastCT + " "); } } hqlSb.Append(") "); if (lastGroup.Key != item.Key) { hqlSb.Append(lastCT); } } //-----------------动态创建 where 语句结束--------------------
项目结构如下,东西不多

是不是觉得很方便?
刚刚用EXTJS 做的一个 demo
imageimage简化NHibernate查询并分页
文章最下面有全部源码以及demo 的下载地址
点我下载Demo
汤晓华 QQ 1881597 MSN [email protected]
2011 05 16
Tags: 

延伸阅读

最新评论

发表评论