Castle ActiveRecord学习实践(7):使用HQL查询

摘要:虽然ActiveRecord为我们提供了Find()FindAll()这样两个静态的查询方法,并且有Where特性可供使用,但是仍然不能解决实际开发中一些复杂的查询,这时我们就需要通过HQL查询来实现。

 

主要内容

1HQL概述

2SimpleQuery查询

3ScalarQuery查询

4.自定义查询

5.使用CallBack

 

一.HQL简单介绍

HQL全名是Hibernate Query Language,它是一种完全面向对象的查询语言。先来看一下HQL最基本的一些用法

1From子句

None.gif from  Post

你也可以为Post起一个别名

None.gif from  Post  as  post

或者省略as

None.gif from  Post post

2Select 子句

None.gif select  Name,Author  from  Blog

也可以使用elements函数来查询一个集合

None.gif select  elements(blog.Posts)  from  Blog blog

3.使用聚合函数

HQL中也可以使用一些聚合函数

None.gif select   count ( * from  Blog blog

 

None.gif select   count (elements(blog.Posts))  from  Blog blog

HQL支持的聚合函数有

None.gif avg (dot.gif),  sum (dot.gif),  min (dot.gif),  max (dot.gif
None.gif
None.gif
count ( *
None.gif
None.gif
count (dot.gif),  count ( distinct  dot.gif),  count ( all dot.gif)

4Where子句

None.gif from  Blog blog  where  blog.Name  =  ‘Terry Lee’

 

None.gif from  Blog blog  where  blog.Name  is   not   null

详细可以参考http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html

 

二.SimpleQuery查询

SimpleQuery是一种最简单的查询,它直接处理HQL语句,并返回一个集合,没有复杂的参数处理。具体用法可以参考下例:

None.gif [ActiveRecord( " Posts " )]
None.gif
None.gif
public   class  Post : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
// dot.gifdot.gif
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif
InBlock.gif    
/// 查询某一类别的所有Posts
InBlock.gif
InBlock.gif    
/// </summary>
InBlock.gif
InBlock.gif    
/// <param name="_strCategory">类别名称</param>
InBlock.gif
ExpandedSubBlockEnd.gif    
/// <returns></returns>

InBlock.gif
InBlock.gif    
public static Post[] GetPostsByCategory(string _strCategory)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        SimpleQuery query 
= new SimpleQuery(
InBlock.gif
InBlock.gif            
typeof(Post),
InBlock.gif
InBlock.gif            
@"from Post post where post.Category = ?",
InBlock.gif
InBlock.gif            _strCategory
InBlock.gif
InBlock.gif            );
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
return (Post[])ExecuteQuery(query);
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif
InBlock.gif    
/// 查询某一时间段内发表的所有Posts
InBlock.gif
InBlock.gif    
/// </summary>
InBlock.gif
InBlock.gif    
/// <param name="start">开始时间</param>
InBlock.gif
InBlock.gif    
/// <param name="end">结束时间</param>
InBlock.gif
ExpandedSubBlockEnd.gif    
/// <returns></returns>

InBlock.gif
InBlock.gif    
public static int[] GetPostsInterval(DateTime start,DateTime end)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        SimpleQuery query 
= new SimpleQuery(
InBlock.gif
InBlock.gif            
typeof(Post),typeof(int),
InBlock.gif
InBlock.gif            
@"select post.Id from Post post where post.Created between ? and ?",
InBlock.gif
InBlock.gif            start,end
InBlock.gif
InBlock.gif            );
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
return (int[])ExecuteQuery(query);
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


看一下简单的测试代码:

None.gif [Test]
None.gif
None.gif
public   void  TestGetPostsByCategory()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
string StrCategory = "Castle";
InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    IList list 
= (IList)Post.GetPostsByCategory(StrCategory);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
int expectedCount = 2;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    Assert.IsNotNull(list);
InBlock.gif
InBlock.gif    Assert.AreEqual(expectedCount,list.Count);
InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif 
None.gif
None.gif[Test]
None.gif
None.gif
public   void  TestGetPostsInterval()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    DateTime start 
= Convert.ToDateTime("2006-01-01");
InBlock.gif
InBlock.gif    DateTime end 
= DateTime.Now;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    IList list 
= (IList)Post.GetPostsInterval(start,end);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
int expectedCount = 2;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    Assert.IsNotNull(list);
InBlock.gif
InBlock.gif    Assert.AreEqual(expectedCount,list.Count);
InBlock.gif
ExpandedBlockEnd.gif}

 

三.ScalarQuery查询

ScalarQuery查询也是一种简单的直接处理HQL的查询,它也没有复杂的参数处理,只不过返回的值不是集合而是单一的值,具体用法参考下例:

None.gif [ActiveRecord( " Blogs " )]
None.gif
None.gif
public   class  Blog : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
// dot.gifdot.gif
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif
InBlock.gif    
/// 查询某作者发表的所有Posts数量
InBlock.gif
InBlock.gif    
/// </summary>
InBlock.gif
InBlock.gif    
/// <param name="_StrAuthor">作者姓名</param>
InBlock.gif
ExpandedSubBlockEnd.gif    
/// <returns></returns>

InBlock.gif
InBlock.gif    
public static int GetPostNumByAuthor(string _StrAuthor)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        ScalarQuery query 
= new ScalarQuery(
InBlock.gif
InBlock.gif            
typeof(Blog),
InBlock.gif
InBlock.gif            
@"select count(elements(blog.Posts)) from Blog blog where blog.Author = ?",
InBlock.gif
InBlock.gif            _StrAuthor
InBlock.gif
InBlock.gif            );
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
return (int)ExecuteQuery(query);
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


看一下简单的测试代码

None.gif [Test]
None.gif
None.gif
public   void  TestGetPostNumByAuthor()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
string _StrAuthor = "Terry Lee";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
int result = Blog.GetPostNumByAuthor(_StrAuthor);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
int expectedCount = 2;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    Assert.AreEqual(expectedCount,result);
InBlock.gif
ExpandedBlockEnd.gif}


四.自定义查询

在实际开发中,我们所面对的查询远不止上面所说得这么简单,有时候我们需要处理一些自定义的参数,或者执行自定义的查询语句,这时需要我们编写自定义的ActiveRecord查询,首先要添加一个类,让它继承于基类ActiveRecordBaseQuery,并覆写Execute()方法(或者实现IactiveRecordQuery接口),如下例所示

None.gif public   class  QueryWithNamedParameters : ActiveRecordBaseQuery
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
private string _authorName = null;
InBlock.gif
InBlock.gif    
private int _maxResults = 2;
InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
public QueryWithNamedParameters()
InBlock.gif
InBlock.gif        : 
base(typeof(Blog)) 
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif 
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
public string AuthorName
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _authorName; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _authorName = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
public int MaxResults
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _maxResults; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _maxResults = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public override object Execute(ISession session)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        String hql 
= "from Blog blog";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
if (_authorName != null)
InBlock.gif
InBlock.gif            hql 
+= " where blog.Author = :author";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        IQuery q 
= session.CreateQuery(hql);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
if (_authorName != null)
InBlock.gif
InBlock.gif            q.SetString(
"author", _authorName);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        q.SetMaxResults(_maxResults);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
return base.GetResultsArray(typeof(Blog), q.List(), nullfalse);
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


使用我们自定义的类

ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
InBlock.gif
InBlock.gif
/// 自定义查询
InBlock.gif
InBlock.gif
/// </summary>
InBlock.gif
InBlock.gif
/// <param name="authorName"></param>
InBlock.gif
ExpandedBlockEnd.gif
/// <returns></returns>

None.gif
None.gif
public   static  Blog[] GetThreeBlogsFromAuthor(  string  authorName )
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    QueryWithNamedParameters q 
= new QueryWithNamedParameters();
InBlock.gif
InBlock.gif    q.AuthorName 
= authorName;
InBlock.gif
InBlock.gif    q.MaxResults 
= 3;
InBlock.gif
InBlock.gif    
return (Blog[]) ExecuteQuery(q);
InBlock.gif
ExpandedBlockEnd.gif}


看一下简单的测试代码

None.gif [Test]
None.gif
None.gif
public   void  TestCustomQuery()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
string _StrAuthor = "Terry Lee";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    IList list 
= Blog.GetThreeBlogsFromAuthor(_StrAuthor);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
int expectedCount = 3;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    Assert.IsNotNull(list);
InBlock.gif
InBlock.gif    Assert.AreEqual(expectedCount,list.Count);
InBlock.gif
ExpandedBlockEnd.gif}

 

五.使用CallBack

还有一种实现方式是使用Execute()方法,这种方式与我们前面所讲的自定义查询是差不多的,只不过不用增加额外的自定义类。

None.gif [ActiveRecord( " Blogs " )]
None.gif
None.gif
public   class  Blog : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//dot.gifdot.gif
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif
InBlock.gif    
/// 通过CallBack执行
InBlock.gif
InBlock.gif    
/// </summary>
InBlock.gif
InBlock.gif    
/// <param name="author"></param>
InBlock.gif
ExpandedSubBlockEnd.gif    
/// <returns></returns>

InBlock.gif
InBlock.gif    
public static Blog[] GetPostsFromAuthor( string author )
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
return (Blog[]) Execute( typeof(Blog), new NHibernateDelegate(GetPostsFromAuthorCallback), author);
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private static object GetPostsFromAuthorCallback(ISession session, object instance )
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
// 创建查询
InBlock.gif

InBlock.gif        IQuery query 
= session.CreateQuery( "from Blog blog where blog.Author = :author" );
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
// 设置参数
InBlock.gif

InBlock.gif        query.SetString(
"author", (string) instance);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
// 获取结果
InBlock.gif

InBlock.gif        IList results 
= query.List();
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
// 转化结果为Array
InBlock.gif

InBlock.gif        Blog[] blogs 
= new Blog[results.Count];
InBlock.gif
InBlock.gif        results.CopyTo(blogs, 
0);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif        
// 返回结果
InBlock.gif

InBlock.gif        
return blogs;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

 

编写测试代码

None.gif [Test]
None.gif
None.gif
public   void  TestGetPostsFromAuthor()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
string _StrAuthor = "Terry Lee";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    IList list 
= Blog.GetPostsFromAuthor(_StrAuthor);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
int expectedCount = 4;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    Assert.IsNotNull(list);
InBlock.gif
InBlock.gif    Assert.AreEqual(expectedCount,list.Count);
InBlock.gif
ExpandedBlockEnd.gif}

 

关于使用HQL查询就介绍到这儿了,相信通过HQL查询可以解决我们开发中的绝大多数的复杂查询问题。

 

 

参考资料

文中主要内容来自于Castle的官方网站http://www.castleproject.org

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值