最近公司在做一款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<BookType> 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 语句结束--------------------
项目结构如下,东西不多
具体代码如下
Filter.cs
/* ***********************************************
* 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
* Email:tension1990@hotmail.com
* QQ:1881597
* 描述 :
* 创建时间:2011/5/15
* 修改历史:
* ***********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Criterion;
namespace Tension.NHibernate.Query
{
/// <summary>
/// 过滤条件
/// </summary>
public class Filter
{
#region 字段属性
public string ParamName { get; set; }
/// <summary>
/// 条件中的字段名称
/// </summary>
public string PropertyName { get; set; }
/// <summary>
/// 条件中的字段值
/// </summary>
public object PropertyValue { get; set; }
/// <summary>
/// HQL占位作用的字段名 区别在于 弱 是关联对象查询 则去处 . 号 如 PropertyName=Group.Name 则PlaceholderPropertyName=GroupName
/// NHibernate 在分析HQL时 若占位符存在 . 会报异常
/// </summary>
public string PlaceholderPropertyName { get; set; }
/// <summary>
/// 字段数据类型
/// </summary>
public string PropertyType { get; set; }
/// <summary>
/// 条件类型
/// </summary>
public string Operation { get; set; }
/// <summary>
/// 条件组连接类型
/// </summary>
public string ConnectionType { get; set; }
/// <summary>
/// 条件组
/// </summary>
public int Group { get; set; }
/// <summary>
/// 组成员索引
/// </summary>
public int Index { get; set; }
private int pindex = 0;
/// <summary>
/// 参数索引位置
/// </summary>
public int PIndex
{
get { return pindex; }
set
{
PlaceholderPropertyName = PropertyName.Replace(".", "") + value;
pindex = value;
}
}
/// <summary>
/// 参数全名
/// </summary>
private string paramName;
/// <summary>
/// 不需要添加到IQuery 的参数集合
/// </summary>
public bool NoAdd { get; set; }
/// <summary>
/// 支持的数据类型的简写
/// </summary>
private string[] PropertyTypes = new string[] { "S", "D", "DEC", "FT", "I", "IS", "IB", "ST", "L", "B", "ARR" };
/// <summary>
/// 支持的比较运算符
/// </summary>
private string[] Operations = new string[] { "EQ", "LT", "<", "GT", ">", "LE", "<=", "GE", ">=", "LK", "LIKE", "LFK", "LIKE%", "RHK", "%LIKE", "NULL", "NOTNULL", "IN", "BT" };
#endregion
#region 构造
/// <summary>
/// 空构造
/// </summary>
public Filter() { }
/// <summary>
///
/// </summary>
/// <param name="paramName"></param>
/// <param name="paramVal"></param>
public Filter(string paramName, object propertyValue)
{
/**
*
* Q_propertyName_S_EQ_AND_0_1
*
* 使用 _ 分割
* 0 位置 Q 是判断字符串是否为查询字符串
* 1 位置 Q_propertyName_S_EQ_AND_0_1 是字段名称
* 2 位置 S 是字段类型
*
* 该位置的其他值有:
* S=string D=DateTime,DEC=decimal,FT=float,I=Int32,IS=Int16,IB=Int64,ST=short,L=Long,B=bool
*
* 3 位置 EQ 是条件类型 比如EQ代表等于
* 4 位置 AND 是 AND 或者 OR 查询组的最后一个查询表达式的 AND 或者 OR 将被忽略
* 5 位置 0 代表的是条件组
* 6 位置 1 代表条件组中条件的顺序
*
* 查询组的组后一个查询成员的 4 位置 值在当前查询组中不起作用
* 若存在下一查询组 则查询组后一个查询成员的的 4 位置 值作为与下一查询组的连接符
*
* 例如
* Q_propertyName0_S_EQ_AND_0_1
* Q_propertyName1_S_EQ_AND_1_1
* Q_propertyName2_S_EQ_AND_2_1
* 以上三个查询条件将被翻译为 (propertyName0 = :propertyName0) and (propertyName1 = :propertyName1) and (propertyName2 = :propertyName2)
*
*
* Q_propertyName0_S_EQ_AND_0_1
* Q_propertyName1_S_EQ_OR_1_1
* Q_propertyName2_S_EQ_AND_1_2
* 以上三个查询条件将被翻译为 (propertyName0 = :propertyName0) and (propertyName1 = :propertyName1 or propertyName2 = :propertyName2)
*
* Q_propertyName0_S_EQ_AND_0_1
* Q_propertyName1_S_EQ_OR_0_2
* Q_propertyName2_S_EQ_AND_1_1
* Q_propertyName3_S_EQ_AND_1_2
* 以上4个查询条件将被翻译为 (propertyName0 = :propertyName0 and propertyName1 = :propertyName1) or (propertyName2= :propertyName2 and or propertyName3= :propertyName3)
*
*
*
*
* */
ParamName = paramName;
if (paramName.IndexOf("Q_") != 0)
{
throw new ArgumentNullException("查询条件[paramName]不是合法的查询语句!必须以 Q_ 开头");
}
this.paramName = paramName;
this.PropertyValue = propertyValue;
//执行解析
Analysis();
}
#endregion
#region 方法
/// <summary>
/// 解析
/// </summary>
private void Analysis()
{
if (paramName == null)
{
throw new ArgumentNullException("查询条件[paramName]不能为空!");
}
string[] param_s = paramName.Split('_');
if (param_s.Length < 7)
{
throw new ArgumentException(string.Format("\n\n 查询条件: {0} 不符合规范,请按照 如下标准:Q_propertyName0_S_EQ_AND_0_0\n", paramName));
}
PropertyName = param_s[1];
//除去关联对象查询时的 . 例如 Group.Name
PlaceholderPropertyName = PropertyName.Replace(".", "");
//字段类别的简写
PropertyType = param_s[2].ToUpper();
if (!PropertyTypes.Contains(PropertyType))
{
throw new ArgumentException("参数字符串中[2]位置(字段类别的简写) 必须为:" + string.Join(",", PropertyTypes));
}
Operation = param_s[3].ToUpper();
if (!Operations.Contains(Operation))
{
throw new ArgumentException("参数字符串中[3]位置(支持的比较运算符) 必须为:" + string.Join(",", Operations));
}
ConnectionType = param_s[4].ToLower();
if (ConnectionType != "and" && ConnectionType != "or")
{
throw new ArgumentException("参数字符串中[4]位置(查询条件的连接方式) 必须为 AND 或者 OR");
}
try
{
Group = int.Parse(param_s[5]);
}
catch (Exception)
{
throw new ArgumentException("参数字符串中[5]位置(代表所属查询组) 必须为整数数字");
}
try
{
Index = int.Parse(param_s[6]);
}
catch (Exception)
{
throw new ArgumentException("参数字符串中[6]位置(代表查询组成员排序) 必须为整数数字");
}
//处理like 是的 value
if ("LK" == Operation || "LIKE" == Operation)
{
PropertyValue = string.Format("%{0}%", PropertyValue);
}
else if ("LFK" == Operation || "LIKE%" == Operation)
{
PropertyValue = string.Format("{0}%", PropertyValue);
}
else if ("RHK" == Operation || "%LIKE" == Operation)
{
PropertyValue = string.Format("%{0}", PropertyValue);
}
//处理 NULL 或者 NOTNULL 查询设置该filter 是否要添加参数到查询
else if ("NULL" == Operation)
{
NoAdd = true;
}
else if ("NOTNULL" == Operation)
{
NoAdd = true;
}
}
/// <summary>
/// 产生 HQL 的 where 部分条件字符串
/// </summary>
/// <returns></returns>
public string CreateHqlPart()
{
if ("LT" == Operation || "<" == Operation)
{
return string.Format("{0} < :{1} ", PropertyName, PlaceholderPropertyName);
}
else if ("GT" == Operation || ">" == Operation)
{
return string.Format("{0} > :{1} ", PropertyName, PlaceholderPropertyName);
}
else if ("LE" == Operation || "<=" == Operation)
{
return string.Format("{0} <= :{1} ", PropertyName, PlaceholderPropertyName);
}
else if ("GE" == Operation || ">=" == Operation)
{
return string.Format("{0} >= {1} ", PropertyName, PlaceholderPropertyName);
}
else if ("LK" == Operation || "LIKE" == Operation)
{
return string.Format("{0} like :{1} ", PropertyName, PlaceholderPropertyName);
}
else if ("LFK" == Operation || "LIKE%" == Operation)
{
return string.Format("{0} like :{1} ", PropertyName, PlaceholderPropertyName);
}
else if ("RHK" == Operation || "%LIKE" == Operation)
{
return string.Format("{0} like :{1} ", PropertyName, PlaceholderPropertyName);
}
else if ("NULL" == Operation)
{
return string.Format("{0} is null ", PropertyName);
}
else if ("NOTNULL" == Operation)
{
return string.Format("{0} is not null ", PropertyName);
}
else if ("IN" == Operation)
{
return string.Format("{0} in (:{1}) ", PropertyName, PlaceholderPropertyName);
}
else if ("BT" == Operation)
{
return string.Format("{0} between (:{1}) and (:{2})", PropertyName, PlaceholderPropertyName + "_0", PlaceholderPropertyName + "_1");
}
else
{
return string.Format("{0} = :{1} ", PropertyName, PlaceholderPropertyName);
}
}
#endregion
}
}
QueryFilter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Collections;
/* ***********************************************
* 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
* Email:tension1990@hotmail.com
* QQ:1881597
* 描述 :
* 创建时间:2011/5/15
* 修改历史:
* ***********************************************/
namespace Tension.NHibernate.Query
{
/// <summary>
/// 查询过滤器
/// </summary>
public class QueryFilter<T> where T : class
{
#region 字段属性
/// <summary>
/// 数据起始位置
/// </summary>
public int DataStart { get; set; }
/// <summary>
/// 每页显示的条数
/// </summary>
public int DataLimit { get; set; }
///// <summary>
///// 数据总数
///// </summary>
//public int DataCount { get; set; }
/// <summary>
/// 排序字段
/// </summary>
public string Sort { get; set; }
private string dir = "asc";
/// <summary>
/// asc desc
/// </summary>
public string Dir { get { return dir; } set { dir = value; } }
/// <summary>
/// 过滤条件集合
/// </summary>
private IList<Filter> filters = new List<Filter>();
/// <summary>
/// 过滤条件缓存
/// </summary>
private static Dictionary<string, string> QueryHqlCache;
/// <summary>
/// 当前的HQL
/// </summary>
public string CurrentHQL { get; set; }
/// <summary>
/// 计算数据条数的HQL
/// </summary>
public string CountHQL { get; set; }
#endregion
#region 构造
/// <summary>
/// 静态构造
/// </summary>
static QueryFilter()
{
QueryHqlCache = new Dictionary<string, string>();
}
#endregion
#region 方法
/// <summary>
/// 增加过滤条件 类型 Filter
/// </summary>
/// <param name="filter"></param>
public void AddFilter(Filter filter)
{
if (filter.PropertyValue.ToString() != "NOTADD")
{
filter.PIndex = filters.Count + 1;
filters.Add(filter);
}
}
/// <summary>
/// 增加过滤条件 类型 string
/// </summary>
/// <param name="filter"></param>
public void AddFilter(string paramName, object obj)
{
AddFilter(new Filter(paramName, obj));
}
/// <summary>
/// 创建查询数据条数的IQuery
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
public IQuery CreateCountQuery(ISession session)
{
if (string.IsNullOrEmpty(CountHQL))
{
InitHQL();
}
IQuery query = session.CreateQuery(CountHQL);
AddParameters(query);
return query;
}
/// <summary>
/// 创建IQuery对象
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
public IQuery CreateQuery(ISession session)
{
InitHQL();
if (!string.IsNullOrEmpty(Sort))
{
CurrentHQL += string.Format(" order by {0} {1}", Sort, Dir);
}
IQuery query = session.CreateQuery(CurrentHQL);
if (DataLimit > 0)
{
query.SetMaxResults(DataLimit).
SetFirstResult(DataStart);
}
AddParameters(query);
return query;
}
/// <summary>
/// 初始化HQL 该方法同事初始化 CurrentHQL 与 CountHQL
/// </summary>
private void InitHQL()
{
CurrentHQL = BuildHql();
CountHQL = CurrentHQL.Replace("from", "select count(*) from");
}
/// <summary>
/// 向 IQuery 添加参数
/// </summary>
/// <param name="query"></param>
private void AddParameters(IQuery query)
{
foreach (var item in filters)
{
if (!item.NoAdd && item.PropertyType == "ARR")
query.SetParameterList(item.PlaceholderPropertyName, item.PropertyValue as object[]);
else if (!item.NoAdd)
{
//query.SetParameter(item.PlaceholderPropertyName, item.PropertyValue);
if (item.Operation == "BT")
{
string[] valarr = item.PropertyValue.ToString().Split('_');
query.SetParameter(item.PlaceholderPropertyName + "_0", ValueConverter.Convert(item.PropertyType, valarr[0]));
query.SetParameter(item.PlaceholderPropertyName + "_1", ValueConverter.Convert(item.PropertyType, valarr[1]));
}
else
{
query.SetParameter(item.PlaceholderPropertyName, ValueConverter.Convert(item.PropertyType, item.PropertyValue));
}
}
}
}
/// <summary>
/// 创建HQL
/// </summary>
/// <returns></returns>
public string BuildHql()
{
string key = CreateQueryFilterKey();
if (QueryHqlCache.ContainsKey(key))
{
return QueryHqlCache[key];
}
else
{
string hqlStr = "";
var queryable = GetSortedFilterGroup();
int groupCount = queryable.Count();
StringBuilder hqlSb = new StringBuilder(string.Format("from {0} t", typeof(T).Name));
if (groupCount != 0)
{
hqlSb.Append(" where ");
}
//-----------------动态创建 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 语句结束--------------------
if (!QueryHqlCache.ContainsKey(key))
{
hqlStr = hqlSb.ToString();
QueryHqlCache[key] = hqlStr;
}
return hqlStr;
}
}
/// <summary>
/// 创建当前查询的 key 用于缓存查询
/// </summary>
/// <returns></returns>
private string CreateQueryFilterKey()
{
var queryable = GetSortedFilterGroup();
StringBuilder key = new StringBuilder();
foreach (var item in queryable)
{
foreach (var _item in item)
{
key.Append(_item.ParamName);
key.Append("&");
}
}
return key.ToString();
}
/// <summary>
/// 获取排序并分组后的查询过滤条件
/// </summary>
/// <returns></returns>
private IOrderedEnumerable<IGrouping<int, Filter>> GetSortedFilterGroup()
{
var queryable = filters.Select(s => s).OrderBy(d => d.Index).GroupBy(f => f.Group).OrderBy(f => f.Key);
return queryable;
}
#endregion
}
}
ValueConverter.cs
/* ***********************************************
* 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
* Email:tension1990@hotmail.com
* QQ:1881597
* 描述 :
* 创建时间:2011/5/15
* 修改历史:
* ***********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tension.NHibernate.Query
{
/// <summary>
/// 值转换器
/// </summary>
public class ValueConverter
{
#region 方法
/// <summary>
/// 转换到对应的类型
/// </summary>
/// <param name="type"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static object Convert(string type, object obj)
{
string val = obj.ToString();
//type : S=string D=DateTime,DEC=decimal,FT=float,I=Int32,I16=Int16,I64=Int64,ST=short,L=Long,B=bool;A=object[]
//"S", "D", "DEC", "FT", "I", "IS", "IB", "ST", "L", "B","ARR"
switch (type)
{
case "S": //string
return val;
case "D": //DateTime
return DateTime.Parse(val);
case "DEC"://decimal
return decimal.Parse(val);
case "FT": //float
return float.Parse(val);
case "I":
return Int32.Parse(val);
case "IS":
return Int16.Parse(val);
case "IB":
return Int64.Parse(val);
case "ST":
return short.Parse(val);
case "L":
return long.Parse(val);
case "B":
if (val == "0")
return false;
if (val == "1")
{
return true;
}
return bool.Parse(val);
case "ARR":
return obj as object[];
default:
return type;
}
}
#endregion
}
}
WebQueryFilter.cs
/* ***********************************************
* 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
* Email:tension1990@hotmail.com
* QQ:1881597
* 描述 :
* 创建时间:2011/5/15
* 修改历史:
* ***********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace Tension.NHibernate.Query
{
/// <summary>
/// 用于web方式的查询过滤器 实现自动注入查询条件
/// </summary>
/// <typeparam name="T"></typeparam>
public class WebQueryFilter<T> : QueryFilter<T> where T : class
{
private string sort_qs = "sort";
private string dir_qs = "dir";
private string start_qs = "start";
private string limit_qs = "limit";
#region 构造
public WebQueryFilter()
: base()
{
}
/// <summary>
/// 自动封装Request.Params 中符合条件的查询参数
/// </summary>
/// <param name="Request">HttpRequest</param>
/// <param name="sort_qs">排序字段在 querystring 中的 名称 指 key </param>
/// <param name="dir_qs">排序方式 querystring 中的 名称 指 key </param>
/// <param name="start_qs">分页时数据起始位置 querystring 中的 名称 指 key </param>
/// <param name="limit_qs">分页时每页的数据条数 querystring 中的 名称 指 key </param>
public WebQueryFilter(HttpRequest Request, string sort_qs, string dir_qs, string start_qs, string limit_qs)
{
}
/// <summary>
/// 参数为 HttpRequest 自动封装Request.Params 中符合条件的查询参数
/// </summary>
/// <param name="Request"></param>
public WebQueryFilter(HttpRequest Request)
{
foreach (var item in Request.Params.Keys)
{
if (item == null)
{
continue;
}
string key = item.ToString();
if (key.IndexOf("Q_") == 0)
{
string[] values = Request.Params.GetValues(key);
if (key.Split('_')[2].ToUpper() == "ARR")
{
base.AddFilter(key, Request.Params.GetValues(key));
}
else
{
string val = Request.Params.Get(key);
base.AddFilter(key, val);
}
}
}
string start = Request.Params.Get(start_qs) ?? "0";
string limit = Request.Params.Get(limit_qs) ?? "max";
if (limit != "max")
{
DataStart = int.Parse(start);
DataLimit = int.Parse(limit);
}
string sort = Request.Params.Get(sort_qs);
string dir = Request.Params.Get(dir_qs) ?? "asc";
if (!string.IsNullOrEmpty(sort))
{
Sort = sort;
Dir = dir;
}
}
#endregion
}
}
简单介绍一下各个类的功能
Filter 主要是对 一个 查询条件进行封装 ,对表达式的解析,值的转换
ValueConverter 是通过约定好的数据类型的简写进行对应的转换
QueryFilter 是将一个查询请求中 所有的 查询条件(Filter) 进行 HQL 的转换,并同时具有Nhibernate 的 IQuery 对象的创建功能,同时通过该类可以进行 多条件查询、分页、排序等操作。
WebQueryFilter 继承自 QueryFilter 主要增加了 ASP.NET 环境下 对查询结果自动封装的功能。QueryFilter 不具有此能力,适用于手动指定查询条件的情况。
通过QueryFilter,只要封装到通用的数据访问类中,大多数查询都不需要进行硬编码。
以下是我的简单的通用数据访问类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tension.NHibernate;
using Tension;
using Tension.NHibernate.Query;
using NHibernate;
namespace Service
{
public static class Extension
{
public static void Query<T>(this GenericDAL<T> gd, DataPage<T> dataPage, QueryFilter<T> queryFilter)
where T : class
{
var session = Tension.NHibernate.NHibernateSessionFactory.GetSession();
IQuery query = queryFilter.CreateQuery(session);
IQuery count_query = queryFilter.CreateCountQuery(session);
object o = count_query.UniqueResult();
int count = int.Parse(o.ToString());
dataPage.Result = query.List<T>();
dataPage.PageIndex = (queryFilter.DataStart / (queryFilter.DataLimit == 0
? 1 : queryFilter.DataLimit)) + 1;
dataPage.PageSize = queryFilter.DataLimit;
dataPage.DateCount = count;
Tension.NHibernate.NHibernateSessionFactory.CloseSession();
}
}
}
代码有点凌乱,以上只是扩展了GenericDAL<T> 因为这部分代码已经是封装好的DLL,所以没放源代码里。
页面上条用业务层查询数据返回结果只需如下
CustomerService Service = new CustomerService(); DataPage<Customer> datapage = new DataPage<Customer>(); var wqf = new WebQueryFilter<Customer>(Request); Service.Query<Customer>(datapage, wqf); Response.Write(new ExtJsGridData<Customer>()
{ success = true, totalCount = datapage.DateCount, data = datapage.Result }.ToJson());
是不是觉得很方便?
刚刚用EXTJS 做的一个 demo
文章最下面有全部源码以及demo 的下载地址
汤晓华 QQ 1881597 MSN tension1990@hotmail.com
2011 05 16

