HQL查询
这里以Northwind数据库为示例数据库
示例数据表:Employees
现在只用雇员表中部分字段。
持久类如下:
public class Employees
{
public virtual int EmployeeID { get; set; }
public virtual string LastName { get; set; }
public virtual string FirstName { get; set; }
public virtual DateTime BirthDate { get; set; }
public virtual string Address { get; set; }
public virtual string City { get; set; }
public virtual string PostalCode { get; set; }
}
映射文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Entities">
<class name="Employees" table="Employees">
<id name="EmployeeID" column="EmployeeID">
<generator class="identity"></generator>
</id>
<property name="LastName" column="LastName" type="String"></property>
<property name="FirstName" column="FirstName" type="String"></property>
<property name="BirthDate" column="BirthDate" type="DateTime"></property>
<property name="Address" column="Address" type="String"></property>
<property name="City" column="City" type="String"></property>
<property name="PostalCode" column="PostalCode" type="String"></property>
</class>
</hibernate-mapping>
开始
(一)From
(1) 返回所有实例(返回所有雇员)
IQuery q = _session.CreateQuery("from Employees");
return q.List<Employees>();
这种返回的是所有实例,且为持久类型。从哪个映射查询,就返回哪个映射的持久类型。
·表别名使用
用法与SQL一样,可以直接在 Employees 后加别名,也可以用as
IQuery q = _session.CreateQuery("from Employees e");
或
IQuery q = _session.CreateQuery("from Employees as e");
·面向对象的理解
从持久类(其实映射的为数据库表Employees表)查询,这里的Employees为持久类,全名为Domain.Entities.Employees
所以,完整的查询应该是:
IQuery q = _session.CreateQuery("from Domain.Entities.Employees as e");
return q.List<Employees>();
所以从这里,可以理解为什么这里要区分大小写
(2)返回部分实例(返回2个雇员)
IQuery q = _session.CreateQuery("from Employees");
q.SetMaxResults(2);
return q.List<Employees>();
(二)Select
(1) 返回所有字段的实例
IQuery q = _session.CreateQuery("select e from Employees e");
return q.List<Employees>();
·select是构造返回类型的关键字,这里与SQL有些不同。Sql中返回所有字段,可以用*,但这里不可以。须用表别名才可以。
(2)返回单个字段(城市)
IQuery q = _session.CreateQuery("select City from Employees");
return q.List<string>();
·这里的City要区分大小写。因为这里是做为对象的属性来使用的。其实全名应该为:
IQuery q = _session.CreateQuery("select e.City from Employees e");
·返回的属性是什么类型,则返回的结果应该为相应的类型。查询城市属性,此属性在持久类中为:
public virtual string City { get; set; }
所以结果为:q.List<string>()
(3)返回多字段(城市与名字)
public IList<Employees> ShowNameCity()
{
IQuery q = _session.CreateQuery("select City,FirstName from Employees");
List<object[]> _objs = q.List<object[]>() as List<object[]>;
IList<Employees> _list = new List<Employees>();
_list = _objs.ConvertAll<Employees>(new Converter<object[], Employees>(GetEmployees));
return _list;
}
public Employees GetEmployees(object[] aa)
{
return new Employees
{
City = (string)aa[0],
FirstName = (string)aa[1]
};
}
这里说明一下,对于返回的多字段这个比较复杂,它返回的是object[] 数组。其实这点也是可以理解的。查询时它找不到与之完全匹配的持久对象,所以返回的是杂项的,可以用多对象多属性来表示这一特征。
可以用单步分解的方式进行返回结果的包装:
IList<Employees> _list = new List<Employees>();
for (int i = 0; i < _objs.Count; i++)
{
_list.Add(new Employees {
City = (string)_objs[i][0],
FirstName = (string)_objs[i][1]
});
}
也可以直接对对象进行包装。这里用到了持久类的构造方法。可以这样:
构造方法:
public Employees(string strCity, string strFirstName)
{
City = strCity;
FirstName = strFirstName;
}
查询:
IQuery q = _session.CreateQuery("select new Employees(City,FirstName) from Employees");
return q.List<Employees>();
·说明一下:构造对象可以随心所欲。可以从新定义一个类(只做为一个实体类型即可),带有相符的属性类型,就可以构造了。
·如果用到默认的构造方法,在加参构造后,应该补充默认的构造方法。
(三) Where(条件)
(1)查询雇员,以城市为条件
IQuery q = _session.CreateQuery("from Employees where City=:City")
.SetString("City", strCity);
return q.List<Employees>();
·HQL条件与SQL区别不大
(2)查询联合的属性
现在改一下持久类与映射文件。定义雇员的一个新属性:全名。类型为全名类型。(保留原先的属性,只增加新属性)
public virtual FName FullName { get; set; }
public class FName
{
public string FirstNamee { get; set; }
public string LastNamee { get; set; }
public string FullName
{
get
{
return FirstNamee + "·" + LastNamee;
}
}
}
<component name="FullName" class="Domain.Entities.FName,Domain">
<property name="FirstNamee" column="FirstName"></property>
<property name="LastNamee" column="LastName"></property>
</component>
查询名字为Nancy的雇员
IQuery q = _session.CreateQuery("from Employees e where e.FullName.FirstNamee=:FirstNamee")
.SetString("FirstNamee", "
return q.List<Employees>();
这里要说明的就是点语法的复合路径