博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NHibernate.3.0.Cookbook第四章第6节的翻译
阅读量:5222 次
发布时间:2019-06-14

本文共 5244 字,大约阅读时间需要 17 分钟。

Using the Hibernate Query Language

使用Hibernate查询语言(HQL)

  到目前为止,我们已经讨论了使用NHibernate的Criteria API和她的新的QueryOver语法的各种查询.NHibernate提供了另外一个更强大的方法,名为Hibernate Query Language,一个融合了熟悉的sql样式的语法与面向对象思想的特定于领域的语言.本节介绍如何使用HQL完成相同的查询.

步骤

1.   完成本章简介中的通用步骤.将新建的控制台程序命名为HQLExample.

2.   添加名为NameAndPrice.hbm.xml的映射文档,别忘了将其设置为嵌入式资源,代码如下:

View Code

3.   在App.config中,在<mapping assembly="Eg.Core"/>元素下面添加<mapping assembly="HQLExample"/>.

4.   在Queries类中,添加下面的方法:

View Code
public IEnumerable
GetMoviesDirectedBy(string directorName){ var hql = @"from Movie m where m.Director = :director"; return _session.CreateQuery(hql) .SetString("director", directorName) .List
();}public IEnumerable
GetMoviesWith(string actorName){ var hql = @"select m from Movie m inner join m.Actors as ar where ar.Actor = :actorName"; return _session.CreateQuery(hql) .SetString("actorName", actorName) .List
();}public Book GetBookByISBN(string isbn){ var hql = @"from Book b where b.ISBN = :isbn"; return _session.CreateQuery(hql) .SetString("isbn", isbn) .UniqueResult
();}public IEnumerable
GetProductByPrice( decimal minPrice, decimal maxPrice){ var hql = @"from Product p where p.UnitPrice >= :minPrice and p.UnitPrice <= :maxPrice order by p.UnitPrice asc"; return _session.CreateQuery(hql) .SetDecimal("minPrice", minPrice) .SetDecimal("maxPrice", maxPrice) .List
();}public IEnumerable
GetMoviePriceList(){ var hql = @"select new NameAndPrice( m.Name, m.UnitPrice) from Movie m"; return _session.CreateQuery(hql) .List
();}public decimal GetAverageMoviePrice(){ var hql = @"select Cast(avg(m.UnitPrice) as Currency) from Movie m"; return _session.CreateQuery(hql) .UniqueResult
();}public IEnumerable
GetAvgDirectorPrice(){ var hql = @"select new NameAndPrice( m.Director, Cast(avg(m.UnitPrice) as Currency) ) from Movie m group by m.Director"; return _session.CreateQuery(hql) .List
();}

5.  在Program.cs中, 为RunQueries方法添加下述代码:

View Code
static void RunQueries(ISession session){  var queries = new Queries(session);  Show("Movies directed by Spielberg:",    queries.GetMoviesDirectedBy(    "Steven Spielberg"));  Show("Movies with Morgan Freeman:",    queries.GetMoviesWith(    "Morgan Freeman"));  Show("This book:",    queries.GetBookByISBN(    "978-1-849513-04-3"));  Show("Cheap products:",    queries.GetProductByPrice(0M, 15M));  Show("Movie Price List:",    queries.GetMoviePriceList());  Show("Average Movie Price:",    queries.GetAverageMoviePrice());  Show("Average Price by Director:",    queries.GetAvgDirectorPrice());}

6.   编译运行,结果如下图所示:

原理

  HQL在语法和SQL的非常相像,但是操作在一个对象级别.我们将所有的查询构建为字符串.很像ADO.NET中的DbCommands,我们围绕这些查询字符串来创建IQuery对象,设置参数值,并且使用List和UniqueResult来执行查询.与Microsoft SQL Server查询中使用"@"类似,在HQL的查询字符串中,我们使用":"来标记参数.当我们设置参数值的时候,不需要包含":".

  • GetMoviesDirectedBy 查询

  有这样一个非常基础的HQL查询:

from Movie mwhere m.Director = :director

  为使代码简洁,为movies取了一个简单的别名m.在这种情况下,有一个隐式的select m语句来投影movies.我们有一个单独的参数director,我们使用她来筛选movies.

  • GetMoviesWith 查询
View Code
select mfrom Movie minner join m.Actors as arwhere ar.Actor = :actorName

  在这个查询中,使用了movies到ActorRoles的联接.注意和SQL的不同之处,我们不需要指定ActorRoles,或是明确使用一个比较式的ON子句.NHibernate已经知道了实体间的关系.我们使用actor的name来筛选actor.就像SQL,因为使用了一个inner join(内联接)查询,actor role上的筛选也会影响到movies.

  • GetProductByPrice 查询
View Code
from Product pwhere p.UnitPrice >= :minPriceand p.UnitPrice <= :maxPriceorder by p.UnitPrice asc

  在这个查询中,使用了两个参数(minPrice和maxPrice)划定了一个价格范围,使用该价格范围来筛选Product.这个查询使用HQL的between来写,代码如下:

View Code
from Product pwhere p.UnitPrice between:minPrice and :maxPriceorder by p.UnitPrice asc

  和SQL一样,order by子句依照单价对products排序.

  • GetMoviePriceList 查询

  有这样的一个简单查询:

select new NameAndPrice(m.Name, m.UnitPrice)from Movie m

  使用HQL时,要关注对象和属性,而不是数据库表和列.该查询将Name属性和UnitPrice属性注入到NameAndPrice类的构造函数中:

public NameAndPrice(string name, decimal unitPrice)
  然后投影产生NameAndPrice的实例.为了使NHibernate知道该类的存在,我们使用了下面的导入映射(import mapping):
<import class="NameAndPrice"/>
  作为一个选择方案,如同criteria和QueryOver一样,我们可以简单的投射Name和UnitPrice,返回一个对象数组list,然后使用LINQ to Objects将她们转换NameAndPrice实例,代码如下:

View Code
var hql = @"select m.Name, m.UnitPrice            from Movie m";var query = session.CreateQuery(hql);return query.List
() .Select(props => new NameAndPrice( (string)props[0], (decimal)props[1]));

  这种情况下,不需要导入NameAndPrice类.

  • GetAverageMoviePrice 查询
select Cast(avg(m.UnitPrice) as Currency)from Movie m

  这个查询中,使用了聚合函数average.返回一个double类型的标量值,所以我们将它转换回NHibernate的Currency类型.在.NET中与之等价类型是decimal,,因此我们使用UniqueResult<decimal>()来执行该查询.

  • GetAvgDirectorPrice 查询
View Code
select new NameAndPrice(    m.Director,    Cast(avg(m.UnitPrice) as Currency))from Movie mgroup by m.Director

  在这个查询中,按照Director来分组.然后将Director 和UnitPrice的平均值注入到NameAndPrice的构造函数中,和刚才一样,由于avg 返回的是double类型,因此需要先将她转换回Currency.

扩展

  除了在实体上映射属性和集合,HQL还允许我们在两个特殊的隐含属性上进行查询:

  • 属性类是实体类型的全名,例如,查询books时,可以使用这样的代码:
from Product p where p.class='Eg.Core.Book'
  • 属性id通常代表实体的POID,不管在实体中我们怎么称呼她.我们都可以使用下面的代码来一次查询3本书:
from Book b where b.id in (@id0, @id1, @id2)

转载于:https://www.cnblogs.com/carfieldSE/archive/2012/07/26/2608648.html

你可能感兴趣的文章
django ORM创建数据库方法
查看>>
创建Oracle synonym 详解
查看>>
php7 新特性整理
查看>>
RabbitMQ、Redis、Memcache、SQLAlchemy
查看>>
linux查看端口占用
查看>>
Sql常见面试题 受用了
查看>>
知识不是来炫耀的,而是来分享的-----现在的人们却…似乎开始变味了…
查看>>
CSS背景颜色、背景图片、平铺、定位、固定
查看>>
口胡:[HNOI2011]数学作业
查看>>
我的第一个python web开发框架(29)——定制ORM(五)
查看>>
中国剩余定理
查看>>
基础笔记一
查看>>
uva 10137 The trip
查看>>
Count Numbers
查看>>
编写高质量代码改善C#程序的157个建议——建议110:用类来代替enum
查看>>
网卡bond技术
查看>>
UITabbarController的UITabbarItem(例:"我的")点击时,判断是否登录
查看>>
UNIX基础知识之输入和输出
查看>>
【洛谷 P1666】 前缀单词 (Trie)
查看>>
数据库锁机制及乐观锁,悲观锁的并发控制
查看>>