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

目录

写在前面

文档与系列文章

一对多查询

总结

写在前面

上篇文章介绍了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关联查询

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

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

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

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

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

HQL关联查询

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

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

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

生成的sql语句为

Criteria API条件查询

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

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

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

 1         /// <summary>
 2         /// Criteria API查询某客户信息与该客户的订单信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrdersByCriteria(Guid customerID)
 7         {
 8             //获得ISession实例
 9             ISession session = NHibernateHelper.GetSession();
10             return session.CreateCriteria(typeof(Customer))
11                 .CreateCriteria("Orders")
12                 .Add(Restrictions.Eq("Customer.CustomerID", customerID))
13                 .List<Customer>();
14         }

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

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

预过滤

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

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

生成的sql语句

没预过滤的

使用预过滤的

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

投影

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

 1         /// <summary>
 2         /// 投影查询某客户信息与该客户的订单信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrdersByProjection(Guid customerID)
 7         {
 8             //获得ISession实例
 9             ISession session = NHibernateHelper.GetSession();
10             IList<Guid> ids = session.CreateCriteria(typeof(Customer))
11                 .SetProjection(Projections.Distinct(
12                 Projections.ProjectionList()
13                 .Add(Projections.Property("CustomerID"))
14                 )
15                 )
16                 .CreateCriteria("Orders")
17         .Add(Restrictions.Eq("Customer.CustomerID", customerID))
18         .List<Guid>();
19             return session.CreateCriteria(typeof(Customer))
20        .Add(Restrictions.In("CustomerID", ids.ToArray<Guid>()))
21        .List<Customer>();
22         }

 

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

生成的sql语句

总结

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

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

博客地址: http://www.cnblogs.com/wolf-sun/
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。

转载:http://www.cnblogs.com/wolf-sun/p/4070935.html

时间: 2024-09-11 15:13:07

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

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

目录 写在前面 文档与系列文章 一对多关系 一个例子 级联删除 级联保存 总结 写在前面 在前面的文章中,我们只使用了一个Customer类进行举例,而在客户.订单.产品中它们的关系,咱们并没有涉及,比如一个客户可以有一个或者多个订单,在数据库中变现为"主外键关系",有时也喜欢称为"父子关系".那么就让我们一起学习,在nhibernate中,是如何处理这种关系的吧? 文档与系列文章 [Nhibernate]体系结构 [NHibernate]ISessionFacto

[Fluent NHibernate]一对多关系处理

目录 写在前面 系列文章 一对多关系 总结 写在前面 上篇文章简单介绍了,Fluent Nhibernate使用代码的方式生成Nhibernate的配置文件,以及如何生成持久化类的映射文件.通过上篇的学习你会发现,Fluent Nhibernate仍然需要引用Nhibernate的两个程序集(Nhibernate.dll和Iesi.Collections.dll),所以与Nhibernate最大的区别就在生成配置文件的方式上面,这里关于Nhibernate的特性方面就不再多赘述,可以参考Nhib

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

目录 写在前面 文档与系列文章 多对多关系关联查询 总结 写在前面 上篇文章介绍了nhibernate中对一对多关系进行关联查询的几种方式,以及在使用过程需要注意的问题.这篇文章对多对多关系的查询处理也采用上篇文章的描述方式进行说明. 文档与系列文章 [Nhibernate]体系结构 [NHibernate]ISessionFactory配置 [NHibernate]持久化类(Persistent Classes) [NHibernate]O/R Mapping基础 [NHibernate]集合

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

MyBitis(iBitis)系列随笔之一:MyBitis入门实例 MyBitis(iBitis)系列随笔之二:类型别名(typeAliases)与表-对象映射(ORM) MyBitis(iBitis)系列随笔之三:简单实现CRUD MyBitis(iBitis)系列随笔之四:多表(多对一查询操作) MyBitis(iBitis)系列随笔之五:多表(一对多关联查询) MyBitis(iBitis)系列随笔之六:mybitis与spring集成          这篇博文介绍的是多表中的一对多表关

NHibernate之旅(10):探索父子(一对多)关联查询

本节内容 关联查询引入 一对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 关联查询引入 在NHibernate中提供了三种查询方式给我们选择:NHibernate查询语言(HQL,NHibernate Query Language).条件查询(Criteria API,Query By Example(QBE)是Criteria API的一种特殊情况).原生SQL(Literal SQL,T-SQL.PL/SQL).这一节分别使用这三种方式来

NHibernate之旅(11):探索多对多关系及其关联查询

本节内容 多对多关系引入 多对多映射关系 多对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 多对多关系引入 让我们再次回顾在第二篇中建立的数据模型: 在图上,我已经清晰的标注了表之间的关系,上两篇分析Customer和Order之间的"外键关系"或者称作"父子关系"."一对多关系"和关联查询,这一篇以Order为中心,分析Order和Product之间的关系,直接看下面一幅图的两张表:

NHibernate之旅(9):探索父子关系(一对多关系)

本节内容 引入 NHibernate中的集合类型 建立父子关系 父子关联映射 结语 引入 通过前几篇文章的介绍,基本上了解了NHibernate,但是在NHibernate中映射关系是NHibernate中的亮点,也是最难掌握的技术.从这篇开始学习这些东西,我将图文结合来说明这里奥秘的知识. 前几篇,我们的例子只使用了一个简单的Customer对象.但是在客户/订单/产品的经典组合中,他们的关系非常复杂?让我们先回顾在第二篇中建立的数据模型. 在图上,我已经清晰的标注了表之间的关系,首先分析Cu

server-SQL Server 的一对多关系查询

问题描述 SQL Server 的一对多关系查询 A表和B表是一对多关系,要如何写sql语句实现图中的效果. 解决方案 SQLServer如下 CREATE TABLE A( id int, name varchar(20) ); CREATE TABLE B( bid int, name varchar(20), pid int ); insert into A(id,name) VALUES(1,'张三'); insert into A(id,name) VALUES(2,'李四'); in

hibernate5(10)注解映射[2]一对多单向关联

在上一篇文章里,我们从端方向一端建立关联关系,完成了从文章到作者的关联关系建立,但在实际的博客网站中,用户肯定还需要获取自己所写的文章,这时可以建立用户(一)对文章(多)的单向关联映射. 先来看我们的一方配置实例 package com.zeng.model; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.F