日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2025/7/14 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NHibernate之旅(10):探索父子(一对多)关联查询 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本節(jié)內(nèi)容

  • 關(guān)聯(lián)查詢引入
  • 一對(duì)多關(guān)聯(lián)查詢
    • 1.原生SQL關(guān)聯(lián)查詢
    • 2.HQL關(guān)聯(lián)查詢
    • 3.Criteria API關(guān)聯(lián)查詢
  • 結(jié)語(yǔ)

關(guān)聯(lián)查詢引入

在NHibernate中提供了三種查詢方式給我們選擇:NHibernate查詢語(yǔ)言(HQL,NHibernate Query Language)、條件查詢(Criteria API,Query By Example(QBE)是Criteria API的一種特殊情況)、原生SQL(Literal SQL,T-SQL、PL/SQL)。這一節(jié)分別使用這三種方式來(lái)關(guān)聯(lián)查詢。

首先看看上一篇我們?yōu)镃ustomer和Order建立的父子關(guān)系:

一對(duì)多關(guān)聯(lián)查詢

1.原生SQL關(guān)聯(lián)查詢

在關(guān)系模型中:可以使用子表作為內(nèi)連接查詢Customer,像這樣:

select * from Customer c inner join Order o on c.CustomerId=o.CustomerId where o.CustomerId=<id of the Customer>

使用父表作為內(nèi)連接查詢Order,像這樣:

select * from Oder o inner join Customer c on o.CustomerId=c.CustomerId where o.OrderId=<id of the Order>

下面我們來(lái)看看在NHibernate中使用原生SQL查詢。這篇來(lái)完成查詢訂單在orderData之后的顧客列表不同查詢的寫(xiě)法。

public IList<Customer> UseSQL_GetCustomersWithOrders(DateTime orderDate) {return _session.CreateSQLQuery("select distinct {customer.*} from Customer {customer}"+" inner join [Order] o on o.Customer={customer}.CustomerId where o.OrderDate> :orderDate").AddEntity("customer", typeof(Customer)).SetDateTime("orderDate", orderDate).List<Customer>(); }

具體情況是:實(shí)例化IQuery接口;使用ISession.CreateSQLQuery()方法,傳遞的參數(shù)是SQL查詢語(yǔ)句;{Customer.*}標(biāo)記是Customer所有屬性的簡(jiǎn)寫(xiě)。 使用AddEntity查詢返回的持久化類(lèi),SetDataTime設(shè)置參數(shù),根據(jù)不同類(lèi)型,方法名不同。

2.HQL關(guān)聯(lián)查詢

查詢訂單在orderData之后的顧客列表的HQL關(guān)聯(lián)查詢寫(xiě)法:

public IList<Customer> UseHQL_GetCustomersWithOrders(DateTime orderDate) {return _session.CreateQuery("select distinct c from Customer c inner join c.Orders o where o.OrderDate > :orderDate").SetDateTime("orderDate", orderDate).List<Customer>(); }

這里使用基于面向?qū)ο蟮腍QL,一目了然,符合面向?qū)ο缶幊塘?xí)慣。

寫(xiě)個(gè)測(cè)試用例測(cè)試UseHQL_GetCustomersWithOrdersTest()查詢方法是否正確:

[Test] public void UseHQL_GetCustomersWithOrdersTest() {IList<Customer> customers = _relation.UseHQL_GetCustomersWithOrders(new DateTime(2008, 10, 1));foreach (Customer c in customers){foreach (Order o in c.Orders){Assert.GreaterOrEqual(o.OrderDate, new DateTime(2008, 10, 1));}}foreach (Customer c in customers){Assert.AreEqual(1, customers.Count<Customer>(x => x == c));} }

首先調(diào)用UseHQL_GetCustomersWithOrders()方法查詢訂單在2008年10月1號(hào)之后的顧客列表,遍歷顧客列表,斷言顧客為預(yù)期的1個(gè),他的訂單時(shí)間在2008年10月1號(hào)之后。OK!測(cè)試成功。注意:這個(gè)測(cè)試用例可測(cè)試本篇所有的關(guān)聯(lián)查詢。

3.Criteria API關(guān)聯(lián)查詢

我們使用CreateCriteria()在關(guān)聯(lián)之間導(dǎo)航,很容易地在實(shí)體之間指定約束。這里第二個(gè)CreateCriteria()返回一個(gè)ICriteria的新實(shí)例,并指向Orders實(shí)體的元素。在查詢中子對(duì)象使用子CreateCriteria語(yǔ)句,這是因?yàn)閷?shí)體之間的關(guān)聯(lián)我們?cè)谟成湮募幸呀?jīng)定義好了。還有一種方法使用CreateAlias()不會(huì)創(chuàng)建ICriteria的新實(shí)例。

這個(gè)例子返回顧客列表有重復(fù)的,不是我們想要的結(jié)果。

public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate) {return _session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders").Add(Restrictions.Gt("OrderDate", orderDate)).List<Customer>(); }

預(yù)過(guò)濾

使用ICriteria接口的SetResultTransformer(IResultTransformer resultTransformer)方法返回滿足特定條件的Customer。上面例子中使用條件查詢,觀察其生成的SQL語(yǔ)句并沒(méi)有distinct,這時(shí)可以使用NHibernate.Transform命名空間中的方法或者使用NHibernate提供的NHibernate.CriteriaUtil.RootEntity、NHibernate.CriteriaUtil.DistinctRootEntity、NHibernate.CriteriaUtil.AliasToEntityMap靜態(tài)方法實(shí)現(xiàn)預(yù)過(guò)濾的作用。那么上面的查詢應(yīng)該修改為:

public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate) {return _session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders").Add(Restrictions.Gt("OrderDate", orderDate)).SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())//或者.SetResultTransformer(NHibernate.CriteriaUtil.DistinctRootEntity).List<Customer>(); }

這個(gè)例子從轉(zhuǎn)換結(jié)果集的角度實(shí)現(xiàn)了我們想要的效果。

投影

調(diào)用SetProjection()方法可以實(shí)現(xiàn)應(yīng)用投影到一個(gè)查詢中。NHibernate.Criterion.Projections是Projection的實(shí)例工廠,Projections提供了非常多的方法,看看下面的截圖,下拉列表中的方法是不是很多啊:

現(xiàn)在可以條件查詢提供的投影來(lái)完成上面同樣的目的:

public IList<Customer> UseCriteriaAPI_GetDistinctCustomers(DateTime orderDate) {IList<int> ids = _session.CreateCriteria(typeof(Customer)).SetProjection(Projections.Distinct(Projections.ProjectionList().Add(Projections.Property("CustomerId")))).CreateCriteria("Orders").Add(Restrictions.Gt("OrderDate", orderDate)).List<int>();return _session.CreateCriteria(typeof(Customer)).Add(Restrictions.In("CustomerId", ids.ToArray<int>())).List<Customer>(); }

我們可以添加若干的投影到投影列表中,例如這個(gè)例子我添加一個(gè)CustomerId屬性值到投影列表中,這個(gè)列表中的所有屬性值都設(shè)置了Distinct投影,第一句返回訂單時(shí)間在orderDate之后所有顧客Distinct的CustomerId,第二句根據(jù)返回的CustomerId查詢顧客列表。達(dá)到上面的目的。這時(shí)發(fā)現(xiàn)其生成的SQL語(yǔ)句中有distinct。我們使用投影可以很容易的組合我們需要的各種方法。

結(jié)語(yǔ)

這一篇通過(guò)上一篇完成的一對(duì)多關(guān)系映射,使用NHibernate中提供的三種查詢方法實(shí)現(xiàn)了父子關(guān)聯(lián)查詢,并初步探討了條件查詢中比較深入的話題。希望對(duì)你有所幫助。下一篇開(kāi)始討論NHibernate中的多對(duì)多映射關(guān)系和查詢。

本系列鏈接:NHibernate之旅系列文章導(dǎo)航

NHibernate Q&A
  • 歡迎加入NHibernate中文社區(qū),一起討論NHibernate知識(shí)!
  • 請(qǐng)到NHibernate中文社區(qū)下載本系列相關(guān)源碼。

下次繼續(xù)分享NHibernate!

轉(zhuǎn)載于:https://www.cnblogs.com/lyj/archive/2008/10/26/1319889.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的NHibernate之旅(10):探索父子(一对多)关联查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。