目录

写在前面

文档与系列文章

一对多查询

总结

写在前面

上篇文章介绍了nhibernate的一对多关系如何配置,以及级联删除,级联添加数据的内容。这篇文章我们将学习nhibernate中的一对多关系的关联查询。前面文章中也介绍的nhibernate的查询:HQL,条件查询,原生SQL查询。

文档与系列文章

[Nhibernate]体系结构

[NHibernate]ISessionFactory配置

[NHibernate]持久化类(Persistent Classes)

[NHibernate]O/R Mapping基础

[NHibernate]集合类(Collections)映射 

[NHibernate]关联映射

[NHibernate]Parent/Child

[NHibernate]缓存(NHibernate.Caches)

[NHibernate]NHibernate.Tool.hbm2net

[NHibernate]Nullables

[NHibernate]Nhibernate如何映射sqlserver中image字段

[NHibernate]基本配置与测试 

[NHibernate]HQL查询 

[NHibernate]条件查询Criteria Query

[NHibernate]增删改操作

[NHibernate]事务

[NHibernate]并发控制

[NHibernate]组件之依赖对象

[NHibernate]一对多关系(级联删除,级联添加)

一对多查询

原生sql关联查询

查询某一个客户的信息,以及该客户所下的订单信息

         /// <summary>
/// 查询某客户信息与该客户的订单信息
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public IList<Customer> GetCustomerOrders(Guid customerID)
{
//获得ISession实例
ISession session = NHibernateHelper.GetSession();
//实例化IQuery接口;使用ISession.CreateSQLQuery()方法,传递的参数是SQL查询语句
return session.CreateSQLQuery("select distinct tb_customer.*,tb_order.* from tb_customer "
+ "inner join tb_order on tb_customer.customerid=tb_order.customerid where tb_customer.customerid=:id")
.AddEntity("Customer", typeof(Customer))
.SetGuid("id", customerID)
.List<Customer>();
}

注意,此时使用的是真正的sql,里面使用的是数据表,这点与hql不同(hql中使用的是面向对象的概念,使用的是数据表映射的实体类对象)。

         /// <summary>
/// 按客户id查询客户信息及订单信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnSearchByID_Click(object sender, EventArgs e)
{
Business.CustomerBusiness customerBusiness = new Business.CustomerBusiness();
this.rptCustomerList.DataSource = customerBusiness.GetCustomerOrders(new Guid("B0720295-9541-40B3-9994-610066224DB8"));
this.rptCustomerList.DataBind();
}

生成的sql语句,因为使用的inner join ,测试的数据为一个客户对应的订单有2个,所以查询出来的数据有2条。

HQL关联查询

使用HQL查询,某一个客户的信息,以及该客户所下的订单信息

         /// <summary>
/// HQL查询某客户信息与该客户的订单信息
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public IList<Customer> GetCustomerOrdersByHQL(Guid customerID)
{
//获得ISession实例
ISession session = NHibernateHelper.GetSession();
return session.CreateQuery("select c from Customer c inner join c.Orders where c.CustomerID=:id")
.SetGuid("id", customerID)
.List<Customer>();
}

通过观察,可以发现inner join 后面的Orders为实体Customer的一个属性,这种面向对象的方式更符合咱们的开发习惯。

生成的sql语句为

Criteria API条件查询

使用Criteria API条件查询,某一个客户的信息,以及该客户所下的订单信息

使用CreateCriteria()在关联之间导航,很容易地在实体之间指定约束。这里第二个CreateCriteria()返回一个ICriteria的新实例,并指向Orders实体的元素。在查询中子对象使用子CreateCriteria语句,这是因为实体之间的关联我们在映射文件中已经定义好了。

还有一种方法使用CreateAlias()不会创建ICriteria的新实例。

         /// <summary>
/// Criteria API查询某客户信息与该客户的订单信息
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public IList<Customer> GetCustomerOrdersByCriteria(Guid customerID)
{
//获得ISession实例
ISession session = NHibernateHelper.GetSession();
return session.CreateCriteria(typeof(Customer))
.CreateCriteria("Orders")
.Add(Restrictions.Eq("Customer.CustomerID", customerID))
.List<Customer>();
}

这个地方需要注意因为在Order和Customer实体中都有CustomerID属性,需要指明是哪个CustomerID。
生成的sql

这种方式得到的结果可能重复,可通过如下方式进行预过滤

预过滤

使用ICriteria接口的SetResultTransformer(IResultTransformer resultTransformer)方法返回满足特定条件的Customer。上面例子中使用条件查询,观察其生成的SQL语句并没有distinct,这时可以使用NHibernate.Transform命名空间中的方法或者使用NHibernate提供的NHibernate.CriteriaUtil.RootEntity、NHibernate.CriteriaUtil.DistinctRootEntity、NHibernate.CriteriaUtil.AliasToEntityMap静态方法实现预过滤的作用。那么上面的查询应该修改为:

         /// <summary>
/// Criteria API查询某客户信息与该客户的订单信息
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public IList<Customer> GetCustomerOrdersByCriteria(Guid customerID)
{
//获得ISession实例
ISession session = NHibernateHelper.GetSession();
return session.CreateCriteria(typeof(Customer))
.CreateCriteria("Orders")
.Add(Restrictions.Eq("Customer.CustomerID", customerID))
//预过滤重复的结果
.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())
//或者.SetResultTransformer(NHibernate.CriteriaUtil.DistinctRootEntity)
.List<Customer>();
}

生成的sql语句

没预过滤的

使用预过滤的

此时查询的Order为一条。通过对比你会发现他们生成的sql语句一样,真正实现过滤的应该是在内存中做的。

投影

调用SetProjection()方法可以实现应用投影到一个查询中。NHibernate.Criterion.Projections是Projection的实例工厂,Projections提供了非常多的方法。

         /// <summary>
/// 投影查询某客户信息与该客户的订单信息
/// </summary>
/// <param name="customerID"></param>
/// <returns></returns>
public IList<Customer> GetCustomerOrdersByProjection(Guid customerID)
{
//获得ISession实例
ISession session = NHibernateHelper.GetSession();
IList<Guid> ids = session.CreateCriteria(typeof(Customer))
.SetProjection(Projections.Distinct(
Projections.ProjectionList()
.Add(Projections.Property("CustomerID"))
)
)
.CreateCriteria("Orders")
.Add(Restrictions.Eq("Customer.CustomerID", customerID))
.List<Guid>();
return session.CreateCriteria(typeof(Customer))
.Add(Restrictions.In("CustomerID", ids.ToArray<Guid>()))
.List<Customer>();
}

我们可以添加若干的投影到投影列表中,例如这个例子我添加一个CustomerId属性值到投影列表中,这个列表中的所有属性值都设置了Distinct投影,第一句返回订单的客户CustomerId,第二句根据返回的CustomerId查询顾客列表。达到上面的目的。这时发现其生成的SQL语句中有distinct。我们使用投影可以很容易的组合我们需要的各种方法。

生成的sql语句

总结

这里介绍了处理一对多关系的关联查询的方式,希望对你有所帮助。

参考地址:http://www.cnblogs.com/lyj/archive/2008/10/26/1319889.html

[NHibernate]一对多关系(关联查询)的更多相关文章

  1. 7.Mybatis关联表查询(这里主要讲的是一对一和一对多的关联查询)

    在Mybatis中的管理表查询这里主要介绍的是一对一和一对多的关联查询的resultMap的管理配置查询,当然你也可以用包装类来实现.不过这里不说,做关联查询的步骤可以简单的总结为以下的几步: 1.分 ...

  2. [NHibernate]一对多关系(级联删除,级联添加)

    目录 写在前面 文档与系列文章 一对多关系 一个例子 级联删除 级联保存 总结 写在前面 在前面的文章中,我们只使用了一个Customer类进行举例,而在客户.订单.产品中它们的关系,咱们并没有涉及, ...

  3. [Fluent NHibernate]一对多关系处理

    目录 写在前面 系列文章 一对多关系 总结 写在前面 上篇文章简单介绍了,Fluent Nhibernate使用代码的方式生成Nhibernate的配置文件,以及如何生成持久化类的映射文件.通过上篇的 ...

  4. Mybatis【15】-- Mybatis一对一多表关联查询

    注:代码已托管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning ,项目是mybatis-11-one2one,需要自取,需要配置maven ...

  5. [NHibernate]多对多关系(关联查询)

    目录 写在前面 文档与系列文章 多对多关系关联查询 总结 写在前面 上篇文章介绍了nhibernate中对一对多关系进行关联查询的几种方式,以及在使用过程需要注意的问题.这篇文章对多对多关系的查询处理 ...

  6. MyBatis关联查询,一对多关联查询

    实体关系图,一个国家对应多个城市 一对多关联查询可用三种方式实现: 单步查询,利用collection标签为级联属性赋值: 分步查询: 利用association标签进行分步查询: 利用collect ...

  7. MyBatis初级实战之六:一对多关联查询

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. MyBitis(iBitis)系列随笔之五:多表(一对多关联查询)

    MyBitis(iBitis)系列随笔之一:MyBitis入门实例 MyBitis(iBitis)系列随笔之二:类型别名(typeAliases)与表-对象映射(ORM) MyBitis(iBitis ...

  9. Mybatis之关联查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

随机推荐

  1. jsp/servlet 中sendRedirect,include,forward区别

    1 sendRedirect response.sendRedirect(); 服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求新的地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以sess ...

  2. 帆软报表FineReport数据库连接编码转换

    1. 问题描述 数据库会以某种编码方式保存与读取数据,FineReport解析时默认使用GBK字符集,若数据库端编码与设计器端编码不一致时,就会导致中文及特殊字符的乱码. FineReport在定义数 ...

  3. 《javascript》高级程序设计——类型转换错误

    容易发生类型转换错误的另一个地方,就是流控制语句.像if之类的语句在确定下一步操作之前,会自动把任何值转换成布尔值.尤其是if语句,如果使用不当,最容易出错.来看下面的例子. function con ...

  4. 数-模(D/A)转换器

    将实现数字信号到模拟信号的转换电流称为数模(D/A)转换器,简称为DAC(Digital - Analog Convert). 目前常见的D/A转化器中,有:权电阻网络D/A转换器.倒T型电阻网络D/ ...

  5. js事件绑定及深入

    学习要点: 1.传统事件绑定的问题2.W3C事件处理函数3.IE事件处理函数4.事件对象的其他补充 事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型).现 ...

  6. Python的列表推导式,字典推导式,集合推导式使用方法

    推导式分为列表推导式(list),字典推导式(dict),集合推导式(set)三种 1.列表推导式也叫列表解析式.功能:是提供一种方便的列表创建方法,所以,列表解析式返回的是一个列表格式:用中括号括起 ...

  7. Google Material Design的图标字体使用教程

    使用教程 1. 打开Material icons下载页 2. 选择要下载的图标 (目前不能多选>_<) 3.选择要下载的格式即可 图标字体使用教程 [方法一] STEP 1: 引入字体文件 ...

  8. 通过xshell远程连接ubuntu

    ubuntu开启sshd服务SSH分客户端openssh-client和openssh-server如果你只是想登陆别的机器的SSH只需要安装openssh-client(ubuntu有默认安装,如果 ...

  9. ZooKeeper 笔记(1) 安装部署及hello world

    先给一堆学习文档,方便以后查看 官网文档地址大全: OverView(概述) http://zookeeper.apache.org/doc/r3.4.6/zookeeperOver.html Get ...

  10. async/await Task Timeout

    async/await Task Timeout 在日常的电脑使用过程中,估计最难以忍受的就是软件界面"卡住""无响应",在我有限的开发生涯中一直都是在挑战 它 ...