NHIbernate学习之旅【六】——关系查询
关系查询有一对多,多对多两种形式,说简单点就是多表查询。NHibernate实现起来比较简单。
首先是建表:建构如下

接下来是实体类:
因为Customer对Order是1对多的关系,所以Customer.CS的实体类如下:
Orders是个集合,这样可以通过用户ID查询到多个订单集合。
代码
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
//public virtual Name Name { get; set; }
public virtual int Version { get; set; }
public virtual ISet<Order> Orders { get; set; }
}
然后还要配置映射文件Customer.hbm.xml
代码
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSample.Domain"
namespace="NHibernateSample.Domain.Entities">
<class name ="Customer">
<id name="Id" column ="CustomerId">
<generator class ="native"/>
</id>
<version name="Version" column="Version" type="integer" unsaved-value="0"/>
<!--<component name="Name" class="NHibernateSample.Domain.Entities.Name,NHibernateSample.Domain">-->
<property name ="FirstName"/>
<property name ="LastName"/>
<!--</component>-->
<!--一对多关系:Customer有一个或多个Orders-->
<set name="Orders" table="[Order]" generic="true" inverse="true">
<key column="Customer" foreign-key="FK_CustomerOrders"/>
<one-to-many class="NHibernateSample.Domain.Entities.Order,NHibernateSample.Domain"/>
</set>
</class>
</hibernate-mapping>
一下引用李永京老师的:
NHibernate支持/定义的几种类型的集合:
Bag:对象集合,每个元素可以重复。例如{1,2,2,6,0,0},在.Net中相当于IList或者IList<T>实现。
Set:对象集合,每个元素必须唯一。例如{1,2,5,6},在.Net中相当于ISet或者ISet<T>实现,Iesi.Collections.dll程序集提供ISet集合。
List:整数索引对象集合,每个元素可以重复。例如{{1,"YJingLee"},{2,"CnBlogs"},{3,"LiYongJing"}},在.Net中相当于ArraryList或者List<T>实现。
Map:键值对集合。例如{{"YJingLee",5},{"CnBlogs",7},{"LiYongJing",6}},在.Net中相当于HashTable或者IDictionary<Tkey,TValue>实现。
实际上,我们大多数情况下使用Set集合类型,因为这个类型和关系型数据库模型比较接近。
foreign-key:可以随便起个名字。
one-to-many代表一对多。
这样我们就完成了父类的配置。
接下来是子类的Order.cs
代码
{
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; }
}
因为一个订单可以有多个产品,一个产品又可以又多个订单,所以是多对多的关系,因此对于用户就是Customer,对于产品就是一个集合。
接下来是Order.hbm.xml
代码
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSample.Domain"
namespace="NHibernateSample.Domain.Entities">
<class name="Order" 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="NHibernateSample.Domain.Entities.Customer,NHibernateSample.Domain"
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 ="NHibernateSample.Domain.Entities.Product,NHibernateSample.Domain"
foreign-key="FK_ProductOrders"/>
</bag>
</class>
</hibernate-mapping>
这里的name的值任意,但column父子类必须一致。
还有一个Product表:
Product.cs
代码
{
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; }
}
Product.hbm.XML 别忘了嵌入资源
代码
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSample.Domain" namespace="NHibernateSample.Domain.Entities">
<class name="NHibernateSample.Domain.Entities.Product,NHibernateSample.Domain" 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="NHibernateSample.Domain.Entities.Order,NHibernateSample.Domain"
foreign-key="FK_OrderProducts"/>
</bag>
</class>
</hibernate-mapping>
关于OrderProduct表我们不用写实体类和映射文件,只要在Order和Product的映射文件中进行配置就行,大家可能已经注意到了就是Order和Product的bag节点中的table=“OrderProduct” ,下面在配置关联的字段,即<KEY>节点。这样在查询的时候Nhibernate会自动帮你关联的。
好了 到此就配置完了,可以开始使用了
首先是一对多的三种查询
以下查询出现:在关键字ORDER附近又语法错误 的话 那是因为order是关键字,要用[]括起来,在ORDER映射文件中的CLASS节点中加Table="[Order]"。
代码
" inner join [Order] o on o.Customer={customer}.CustomerId where o.Orderid= :orderid")
.AddEntity("customer", typeof(Customer))
.SetInt32("orderid", orderid)
.List<Customer>();
代码
{
return _session.CreateQuery("select distinct c from Customer c inner join c.Orders o where o.OrderDate > :orderDate")
.SetDateTime("orderDate", orderDate)
.List<Customer>();
}
代码
{
return _session.CreateCriteria(typeof(Customer))
.CreateCriteria("Orders")
.Add(Restrictions.Gt("OrderDate", orderDate))
.List<Customer>();
}
再就是多对多的查询,和一对多没多大区别:
代码
{
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 p.ProductId= :OrderId")
.AddEntity("customer", typeof(Customer))
.SetInt32("OrderId", orderid)
.List<Customer>();
}
代码
{
return _session.CreateQuery("select distinct c from Customer c ,"
+ " c.Orders.elements o where o.OrderDate > :orderDate")
.SetDateTime("orderDate", orderDate)
.List<Customer>();
}
代码
{
return _session.CreateCriteria(typeof(Customer))
.CreateCriteria("Orders")
.CreateCriteria("Products")
.Add(Restrictions.Eq("Name", strname))
.List<Customer>();
}
以上查询都经过测试,都是通过一张表的查询返回另一种表的数据。

浙公网安备 33010602011771号