摘要

上一篇文章介绍了NHibernate HQL,他的缺点是不能够在编译时发现问题。如果数据库表结构有改动引起了实体关系映射的类有改动,要同时修改这些HQL字符串。这篇文章介绍NHibernate面向对象的Criteria查询。他提供了很多API接口,可以实现“私人订制”式的面向对象查询。

作为对照,本篇文章将上篇文章的八个HQL查询全部用Criteria查询写一遍,读者可以自己感受下他们之间的区别。

本篇文章的代码可以到NHibernate查询下载

1、创建Criteria对象,查询所有Customer对象信息

         public IList<Customer> QueryAllCriteria()
{
return Session.CreateCriteria<Customer>().List<Customer>();
}

ISession.CreateCriteria方法返回持久化查询对象的ICriteria实例,他是使用Criteria查询的第一步。传入一个类型参数,表示是对哪一个实体类持久化对象的查询实例。List方法返回持久化类的所有对象。

2、CreateAlias方法创建别名

         public IList<Customer> QueryAllCriteria()
{
return Session.CreateCriteria<Customer>()
.CreateAlias("Customer", "c").List<Customer>();
}

3、指定对象返回数组

         public IList<int> SelectIdCriteria()
{
IList<int> ids = Session.CreateCriteria(typeof(Customer))
.SetProjection(Projections.Distinct(Projections.ProjectionList().Add(Projections.Property("Id"))))
.List<int>();
return ids;
}

ICriteria.SetProjection方法将应用投影到查询中,Projections有很多静态方法生成Distinct、GroupBy、Max、Min、Avg、Sum等投影。

4、添加查询条件

         public IList<Customer> GetCustomerByNameCriteria(string firstName, string lastName)
{
return Session.CreateCriteria<Customer>()
.Add(Restrictions.And(
Restrictions.Eq("FirstName", firstName), Restrictions.Eq("LastName", lastName))
).List<Customer>();
} public IList<Customer> GetCustomersStartWithCriteria()
{
var list = Session.CreateCriteria<Customer>().Add(Restrictions.Like("FirstName", "J%")).List<Customer>();
return list.ToList();
}

ICriteria.Add方法用来添加where条件,Restrictions类提供了很多生成查询条件的API方法。

Restrictions.And方法和Restrictions.Or方法对应SQL的and和or条件,可以传入多个条件对象拼接and/or子句,可以灵活地使用括号进行分组。

示例中的Restrictions.Eq方法和Restrictions.Like方法是最常用的Restrictions方法API。

此外,Restrictions还提供Between、Ge、Gt、Le、Lt、In、IsNotNull、IsNull、Where等多个API方法,可以满足生成大部分查询条件。

5、order by

         public IList<Customer> GetCustomersOrderByCriteria()
{
var list = Session.CreateCriteria<Customer>().AddOrder(new NHibernate.Criterion.Order("FirstName", true)).List<Customer>();
return list.ToList();
}

ICriteria.AddOrder方法添加order子句,传入Criteria.Order对象。Criteria.Order类构造函数传入两个参数,第一个参数表示对哪个属性进行排序,第二个字段表示是升序还是降序,true是升序,false是降序。

6、关联查询

1)按分组查询客户Id及客户关联的订单数量

         public IList<object[]> SelectOrderCountCriteria()
{
var query = Session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders")
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("Id"))
.Add(Projections.RowCount()));
return query.List<object[]>();
}

对查询进行分组通用的代码是:

            var query = Session.CreateCriteria(typeof(类名))
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("属性名"))
.Add(Projections.RowCount() | Projections.Max("Max投影属性名") | Projections.Sum("Sum投影属性名")));

因为要对Order记录进行分组统计,所以使用CreateCriteria("Orders")创建与Orders的关联。

2)查询在指定日期到当前内所有下订单客户信息

         public IList<Customer> GetCustomersOrderDateGreatThanCriteria(DateTime orderDate)
{
return Session.CreateCriteria<Customer>().CreateCriteria("Orders").Add(Restrictions.Gt("Ordered", orderDate))
.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())
.List<Customer>();
}

ICriteria.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())的结果相当于对HQL查询使用了distinct子句。

3)查询所有订单数量大于2的客户信息

         public IList<Customer> GetCustomersOrderCountGreaterThanCriteria()
{
var query = Session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders")
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("Id"))
.Add(Projections.RowCount()));
IList<object[]> groups = query.List<object[]>(); IList<int> ids = groups.Where(g => (int)g[] > ).Select(g => (int)g[]).ToList(); return Session.CreateCriteria(typeof(Customer))
.Add(Restrictions.In("Id", ids.ToArray<int>()))
.List<Customer>();
}

因为ICriteria目前不支持对Group分组结果进行Having筛选,因此必须先对Customer和Orders的关联查询以Customer.Id进行分组,得到Customer.Id和Order数量作为属性的对象的集合,对这个集合执行linq查询,得到订单数量大于2的客户Id集合,最后用Restrictions.In方法对Customer对象集合进行筛选,选出Customer.Id在订单数量大于2的客户Id集合内的客户信息。这样就能够实现Having的查询功能。

结语

NHibernate Criteria查询优点是完全面向对象,ICriteria对象提供了大量的API函数实现完全面向对象的查询语句。可以在编译时发现问题。在更改实体类属性后(如果改动不大),不怎么需要修改查询语句。缺点是功能有限,写复杂的分组查询和条件查询比较困难。一般情况下,在写简单查询的时候用Criteria查询,在写复杂查询的时候使用HQL或者Linq to NHibernate。

NHibernate系列文章二十三:NHibernate查询之Criteria查询(附程序下载)的更多相关文章

  1. NHibernate系列文章二十五:NHibernate查询之Query Over查询(附程序下载)

    摘要 这一篇文章介绍在NHibernate 3.2里引入的Query Over查询,Query Over查询跟Criteria查询类似.首先创建IQueryOver对象,然后通过调用该对象的API函数 ...

  2. NHibernate系列文章二十二:NHibernate查询之HQL查询(附程序下载)

    摘要 NHibernate提供了多种查询方式,最早的HQL语言查询.Criteria查询和SQL Query,到NHibernate 3.0的Linq NHibernate,NHIbernate 4. ...

  3. NHibernate系列文章二十六:NHibernate查询之SQL Query查询(附程序下载)

    摘要 NHibernate在很早的版本就提供了SQL Query(原生SQL查询),对于很复杂的查询,如果使用其他的查询方式实现比较困难的时候,一般使用SQL Query.使用SQL Query是基于 ...

  4. NHibernate系列文章二:创建NHibernate工程

    摘要 这篇文章介绍了如何创建一个简单的使用NHibernate的控制台应用程序,包括使用NuGet.简单的配置.单表映射.对NHibernate配置文件添加智能提示.使用ISessionFactory ...

  5. NHibernate系列文章二十一:延迟加载

    摘要 NHibernate的延迟加载机制是很重要的内容.通过关系映射将数据库表之间的关系映射成对象之间的关系,如果没有延迟加载机制,从主表的一个对象的查询将直接查询出所有与该对象关联的其他对象,如果关 ...

  6. NHibernate系列文章一:NHibernate介绍

    摘要 NHibernate是一个成熟的开源的面向对象的.net映射框架.大量的实际项目中正在使用该框架.他是建立在ADO.Net基础之上.目前的版本是NHibernate 4.0.4.本系列文章都是基 ...

  7. NHibernate系列文章九:NHibernate对象二级缓存上

    摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...

  8. NHibernate系列文章十七:NHibernate Session管理(附程序下载)

    摘要 NHibernate的Session的管理涉及到NHibernate的两个最重要的对象ISessionFactory和ISession.ISessionFactory的生成非常消耗资源,通常都在 ...

  9. NHibernate系列文章八:NHibernate对象一级缓存

    摘要 Nhibernatea缓存非常强大,按照缓存存储在Session对象还是SessionFactory对象分为一级缓存和二级缓存. 一级缓存存在于Session对象里,也叫Session缓存,由S ...

随机推荐

  1. windows下使用ffmpeg进行视频转换和截图。

    author:fanfq(xiaoban) Email:fangqing.fan#gmail.comlink:http://fanfq.iteye.com/admin/blogs/655569chan ...

  2. 【原创】关于不同分支代码的Merge有了透彻的理解

    多分支开发,Merge是一个绕不过的话题,不管是Git还是SVN,公司用的是SVN,之前对于SVN的Merge没有很好的研究,出了些状况,这个问题不解决,顺畅地进行多分支开发就是海市蜃楼,下定决心把这 ...

  3. cxxnet在windows下配置遇到的问题

    I compiled the dmlc-core and rabbit. When I compile the new version of CXXNET, there are compile err ...

  4. jquery特效大全

    http://www.oschina.net/project/tag/300/jquery-effects

  5. pstools使用教程

    pstools是sysinternals开发的一个功能强大的nt/2k远程管理工具包. 官方网址为http://www.sysinternals.com/ 下载地址为http://www.sysint ...

  6. Android模拟器连接本李服务器localhost

    Android模拟(simulator)把它自己作为了localhost,也就是说,代码中使用 localhost或者127.0.0.1来访问,都是访问模拟器自己! 如果你想在模拟器simulator ...

  7. <<redis设计和实现>>读书笔记

    redis如何实现主从同步的高效率?? 主从复制的同步有一个命令数据的同步文本,然后利用两个不同服务器的偏移量来进行进行同步,避免每次都是全部同步(并非会保存所有的命令数据,而是会有一个缓冲区(比如1 ...

  8. 深入详解DataTable

    在学习DataTable知识之前,我们有必要了解下ADO.NET.以下摘自MSDN: ADO.NET 对 Microsoft SQL Server 和 XML 等数据源以及通过 OLE DB 和 XM ...

  9. Spark算上下基线

    def baseLine(sc: SparkContext): Unit = { println("--------------------baseLine start----------- ...

  10. The project: project which is referenced by the classpath, does not exist.

    有个java工程运行时报The project: project which is referenced by the classpath, does not exist.错误 上网查解决方案,说是将 ...