[轉]NHibernate之旅(11):探索多對多關係及其關聯查詢

來源:互聯網
上載者:User

標籤:blog   http   io   os   使用   ar   strong   for   檔案   

本節內容

  • 多對多關係引入
  • 多對多映射關係
  • 多對多關聯查詢
    • 1.原生SQL關聯查詢
    • 2.HQL關聯查詢
    • 3.Criteria API關聯查詢
  • 結語
多對多關係引入

讓我們再次回顧在第二篇中建立的資料模型:

在圖上,我已經清晰的標註了表之間的關係,上兩篇分析Customer和Order之間的“外鍵關係”或者稱作“父子關係”、“一對多關聯性”和關聯查詢,這一篇以Order為中心,分析Order和Product之間的關係,直接看下面一幅圖的兩張表:

上面兩張表關係表達的意思是:Order有多個Products,Product屬於多個Orders。我們稱Order和Product是多對多關係,這一篇我們來深入討論在NHibernate如何映射多對多關係及其多對多關聯查詢。

多對多映射關係1.Order有多個Products

有了上兩篇的基礎,現在直奔主題,建立關係。大家可以把這篇的代碼作為模板,以後在工作中參考。

修改Order.cs類代碼如下:

namespace DomainModel.Entities{    public class Order    {        public virtual int OrderId { get; set; }        public virtual DateTime OrderDate { get; set; }        //多對一關聯性:Orders屬於一個Customer         public virtual Customer Customer { get; set; }        //多對多關係:Order有多個Products         public virtual IList<Product> Products { get; set; }    }}

修改Order.hbm.xml對應檔如下:

<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"                    assembly="DomainModel" namespace="DomainModel">    <class name="DomainModel.Entities.Order,DomainModel" table="`Order`" >    <id name="OrderId" column="OrderId" type="Int32" unsaved-value="0">      <generator class="native" />    </id>    <property name="OrderDate" column="OrderDate" type="DateTime" not-null="true" />    <!--多對一關聯性:Orders屬於一個Customer-->    <many-to-one name="Customer" column="Customer" not-null="true"                 class="DomainModel.Entities.Customer,DomainModel"                 foreign-key="FK_CustomerOrders" />    <!--多對多關係:Order有多個Products-->    <bag name="Products" generic="true" table="OrderProduct">         <key column="`Order`" foreign-key="FK_OrderProducts"/>         <many-to-many column="Product"                     class ="DomainModel.Entities.Product,DomainModel"                     foreign-key="FK_ProductOrders"/>    </bag>  </class></hibernate-mapping>

在多對多關係中,其兩方都使用Bag集合和many-to-many元素。看看上面各個屬性和one-to-many,many-to-one屬性差不多。

2.Product屬於多個Orders

在項目DomainModel層的Entities檔案夾中建立Product.cs類,編寫代碼如下:

namespace DomainModel.Entities{    public class Product    {        public virtual int ProductId { get; set; }        public virtual string Name { get; set; }        public virtual float Cost { get; set; }        //多對多關係:Product屬於多個Orders        public virtual IList<Order> Orders { get; set; }    }}

在項目DomainModel層的Mappings檔案夾中建立Product.hbm.xml對應檔,編寫代碼如下:

<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"                    assembly="DomainModel" namespace="DomainModel">  <class name="DomainModel.Entities.Product,DomainModel" table="Product">        <id name="ProductId" column ="ProductId" type="Int32" unsaved-value="0">      <generator class="native"/>    </id>        <property name="Name" column="Name" type="string" not-null="true" length="50"/>    <property name="Cost" column="Cost" type="float" not-null="true"/>     <!--多對多關係:Product屬於多個Orders-->    <bag name="Orders" generic="true" table="OrderProduct">        <key column="Product" foreign-key="FK_ProductOrders"/>        <many-to-many column="`Order`"                     class="DomainModel.Entities.Order,DomainModel"                    foreign-key="FK_OrderProducts"/>    </bag>      </class></hibernate-mapping>
多對多關聯查詢

使用NHibernate中提供的三種查詢方法實現多對多關聯查詢,查詢返回所有訂單和產品的顧客列表。

1.原生SQL關聯查詢
public IList<Customer> UseSQL_GetCustomersWithOrdersHavingProduct(DateTime orderDate){    return _session.CreateSQLQuery("select distinct {customer.*} from Customer {customer}" +    " inner join [Order] o on o.Customer={customer}.CustomerId"+    " inner join OrderProduct op on o.OrderId=op.[Order]"+    " inner join Product p on op.Product=p.ProductId where o.OrderDate> :orderDate")        .AddEntity("customer", typeof(Customer))        .SetDateTime("orderDate", orderDate)        .List<Customer>();}

這裡需要使用Join告訴查詢如何在表之間關聯。無論多麼複雜的關係,我們必須在查詢語句中指定傳回值。這裡使用AddEntity設定返回的實體。

2.HQL關聯查詢
public IList<Customer> UseHQL_GetCustomersWithOrdersHavingProduct(DateTime orderDate){    return _session.CreateQuery("select distinct c from Customer c ,"        + " c.Orders.elements o where o.OrderDate > :orderDate")        .SetDateTime("orderDate", orderDate)        .List<Customer>();}

因為在對應檔已經定義實體之間一對多、多對多關係,NHibernate通過對應檔知道如何去關聯這些實體,我們不需要在查詢語句中重複定義。這裡使用查詢和上一篇使用HQL關聯查詢語句一樣,NHibernate完全可以去關聯對象,實現查詢訂單和產品。

3.Criteria API關聯查詢

因為實體之間的關聯我們在對應檔中已經定義好了。所以我們在查詢子物件使用子CreateCriteria語句關聯對象之間導航,可以很容易地在實體之間指定約束。這裡第二個CreateCriteria()返回ICriteria的新執行個體,並指向Orders實體的元素。第三個指向Products實體的元素。

public IList<Customer> UseCriteriaAPI_GetCustomerswithOrdersHavingProduct(){    return _session.CreateCriteria(typeof(Customer))        .Add(Restrictions.Eq("Firstname","YJing"))        .CreateCriteria("Orders")        .Add(Restrictions.Gt("OrderDate",new DateTime(2008,10,1)))        .CreateCriteria("Products")        .Add(Restrictions.Eq("Name","Cnblogs"))        .List<Customer>();}

下面我用一幅圖簡單明了的說明這段代碼神秘之處,也顯示了一些約束條件。

編寫一個測試案例測試UseCriteriaAPI_GetCustomerswithOrdersHavingProduct()方法,遍曆列表,看看產品名稱是否為“Cnblogs”,OK!測試通過。

[Test]public void UseCriteriaAPI_GetCustomerswithOrdersHavingProductTest(){    IList<Customer> customers = _relation.UseCriteriaAPI_GetCustomerswithOrdersHavingProduct();    bool found = false;    foreach (Customer c in customers)    {        foreach (Order o in c.Orders)        {            foreach (Product p in o.Products)            {                if (p.Name == "Cnblogs")                {                    found = true;                    break;                }            }        }    }    Assert.IsTrue(found);}

下面再寫個簡單例子查詢產品Id所關聯的一些顧客,測試案例同上面差不多,自己修改下就可以啦。

public IList<Customer> UseCriteriaAPI_GetCustomerswithOrdersHavingProduct(int productId){    return _session.CreateCriteria(typeof(Customer))        .CreateCriteria("Orders")        .CreateCriteria("Products")        .Add(Restrictions.Eq("ProductId", productId))        .List<Customer>();}
結語

這一篇通過全盤代碼的形式完成NHibernate中的多對多關係映射,使用NHibernate中提供的三種查詢方法實現了多對多關聯查詢。希望對你有所協助,多多練習。我們下次繼續討論NHibernate話題,像消極式載入、立即載入、對象狀態等話題,關於朋友回複說討論更多話題,我只能說,再等等吧,慢慢來,這才第十一篇,先把基礎的問題弄清楚。

[轉]NHibernate之旅(11):探索多對多關係及其關聯查詢

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.