NHibernate查询语句(HQL)
NHibernate中的查询方法
在NHibernate中提供了三种查询方式给我们选择:NHibernate查询语言(HQL,NHibernate Query Language)、条件查询(Criteria API ,Query By Example(QBE)是Criteria API的一种特殊情况)、原生SQL(Literal SQL、-SQL、PL\SQL)。每个人有不同的喜好和特长,可以根据自己的情况选择使用其中的一种或几种。
NHibernate查询语句(HQL)
NHibernate查询语句(HQL,NHibernate Query Language)是NHibernate特有的基于面向对象的SQL查询语句,它具有继承、多态和关联等特性。实际上是用OOP中的对象和属性映射了数据库中的表和列。
例子:slect c.Firstname from Customer c
Customer是数据库表,Firstname是列:对于HQL:Customer是一个对象,Firstname是Customer对象的属性。相比之下SQL语句非常灵活,但是没有编译时语法验证支持。
基础语法:from字句,select字句,where字句,order by字句,group by字句。
注意:HQL不区分大小写。
1.from字句
1)简单用法:返回表中所有数据。
Public IList<Customer>From()
{
//返回所有Customer类的实例
Return _session.CreateQuery(“from Cutomer”).List<Customer>();
}
2)使用别名:使用as来赋予表的别名,as可以省略。
Public IList<Customer>FromAlias()
{
//返回所有Customer类的实例,Customer赋予了别名customer
Return _session.CreateQuery(“from Customer as customer”).List<Customer>();
}
3)笛卡尔积:出现多个类,或者分别使用别名,返回笛卡尔积或者称为”交叉”链接。
2.select字句
1)简单用法:在结果集中返回指定的对象和属性。
Public IList<int>Select()
{
//返回所有Customer的CustomerId
Return _session.CreateQuery(“select c.CustomerId from Customer c”).List<int>();
}
2)数组:用Object[]的数组返回多个对象和/或多个属性,或者使用特殊的elements功能,注意一般要结合group by 使用。
Public IList<object[]>SelectObject()
{
Return _session.CreateQuery(“select c.Firstname,count(c.Firstname) from Customer c group by c.Firstname”).List<object[]>();
}
3)统计函数:用Object[]的数组返回属性统计函数的结果,注意统计函数的变量也可以是集合count(elements(c.CustomerId))
Public IList<object[]>AggregateFunction()
{
Return _session.CreateQuery(“select avg(c.CustonerId),sum(c.CustomerId),count(c) from Customer c”)
}
4)Distinct用法:distinct和all关键字的用法和语义与SQL相同。实例:获取不同Customer的FirstName。
Publci IList<string>Distinct()
{
Return _session.CreateQuery(“select distinct c.Firstname from Customer c”).List<string>();
}
3.where字句
Where字句让你缩小你要返回的实例的列表范围。
Public IList<Customer>Where()
{
Return _session.CreateQuery(“select from Customer c where c.Firstname=’name’).List<Customer>();
}
Where字句允许出现的表达式包括了在SQL中大多数情况:
数学操作符:+,-,*,/
真假比较操作符:=,>=,<=,<>,!=,like
逻辑操作符:and,or,not
字符串连接操作符:||
SQL变量函数:upper(),lower()
没有前缀的():表示分组
In,between,is null
位置参数:?
命名参数:name,:start_date,:x1
SQL文字:’foo’,69,’1970-01-01 10:00:01.0’
枚举值或常量:Color.Tabby
4.order by字句
按照任何返回的类或者组件的属性排序:asx升序、desc降序。
Public IList<Customer>Orderby()
{
Return _session.CreateQuery(“select from Customer c order by c.Firstname asc,c.Lasrname desc”).List<Customer>();
}
5.group by 字句
按照任何返回的类或者组件的属性进行分组。
Public ILsit<object[]>Groupby()
{
Return _session.CreateQuery(“select c.Firstname,count(c.Firstname ) from Customer c group by c.Firstname”).List<object[]>();
}
实例分析:
实例1:按照FirstName查询顾客:
Public IList<Customer>GetCustomerByFirstname(string first name)
{
//写法1
//return _session.CreateQuery(“select from Customer c where c.Firstname=””+firstname+””).List<Customer>();
//写法2
//return _session.CreateQuery(“select from Customer c where c.Firstname=?”).SetString(0,firstname).List<Customer>();
//写法3
Return _session.CreateQuery(“select from Customer c where c.Firstname=:fn”).SetString(“fn”,firstname).List<Customer>();
}
书写HQL参数有四种写法:
写法1:可能会引起SQL注入。
写法2:ADO.NET风格的?参数,NHibernate的参数从0开始计数。
写法3:命名参数用:name的形式在查询字符串中表示,这是IQuery接口把实际参数绑定到命名参数。
写法4:命名的参数列表,把一些参数添加到一个集合列表中的形式,比如可以查询数据是否在这个集合列表中。
使用命名参数有一些好处:命名参数不依赖于它们在查询字符串中出现的顺序;在同一个查询中可以使用多次;它们的可读性好。所有在书写HQL使用参数的时候推荐命名参数形式。
测试:判断查询出来的数据的FirstName属性是不是”young”
[Test]
Public void GetCustomerByFirstnameTest()
{
IList<Customer> customers=_queryHQL.GetCustomersByFirstname(“young”);
Assert.AreEqual(1,customers.Count);
Foreach(var c in customers)
{
Assert.AreEqual(“young”,c.Firstname);
}
}
测试2:获取顾客ID大于CustomerId的顾客:
Public IList<Customer>GetCustometWithCustomerIdGreaterThan(int customerId)
{
Return _session.CreateQuery(“select from Customer c where c.CustomerId>:cid”).SetInt32(“cid”,customerId).List<Customer>();
}