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

简介:
摘要:虽然 ActiveRecord 为我们提供了 Find() FindAll() 这样两个静态的查询方法,并且有 Where 特性可供使用,但是仍然不能解决实际开发中一些复杂的查询,这时我们就需要通过 HQL 查询来实现。
 
主要内容
1 HQL 概述
2 SimpleQuery 查询
3 ScalarQuery 查询
4 .自定义查询
5 .使用 CallBack
 
一. HQL 简单介绍
HQL 全名是Hibernate Query Language,它是一种完全面向对象的查询语言。先来看一下HQL最基本的一些用法
1 From子句
None.gif from  Post
你也可以为Post起一个别名
None.gif from  Post  as  post
或者省略as
None.gif from  Post post
2 Select 子句
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)
4 Where子句
None.gif from  Blog blog  where  blog.Name  =  ‘Terry Lee’
 
None.gif from  Blog blog  where  blog.Name  is   not   null
 
二.SimpleQuery查询
SimpleQuery 是一种最简单的查询,它直接处理HQL语句,并返回一个集合,没有复杂的参数处理。具体用法可以参考下例:
None.gif [ActiveRecord( " Posts " )]
None.gif
None.gif
public   class  Post : ActiveRecordBase
None.gif
ExpandedBlockStart.gif
{
InBlock.gif
InBlock.gif    
// dot.gifdot.gif
InBlock.gif

ExpandedSubBlockStart.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.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.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.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.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.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.gif
{
InBlock.gif
InBlock.gif    
// dot.gifdot.gif
InBlock.gif

ExpandedSubBlockStart.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.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.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.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.gif    
{
InBlock.gif
InBlock.gif 
InBlock.gif
ExpandedSubBlockEnd.gif    }

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

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

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public override object Execute(ISession session)
InBlock.gif
ExpandedSubBlockStart.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 /// <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.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.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.gif
{
InBlock.gif
InBlock.gif    
//dot.gifdot.gif
InBlock.gif

ExpandedSubBlockStart.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.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.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.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查询可以解决我们开发中的绝大多数的复杂查询问题。












本文转自lihuijun51CTO博客,原文链接: http://blog.51cto.com/terrylee/67665  ,如需转载请自行联系原作者

相关文章
FluentMybatis Update语法 | FluentMybatis实践
FluentMybatis Update语法 | FluentMybatis实践
FluentMybatis Update语法 | FluentMybatis实践